how to make django default user when using formsets - python

I have this model that i want to make the create_by default for current user
class order(models.Model):
name = models.CharField(max_length=300, null=True,)
description = models.CharField(max_length=300, null=True,blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
created_by = models.CharField(max_length=200,default=None,null=True,blank=True)
in Django models I cant use request.user
I tried in views.py but i cant do it since i am using modelformsets
I tried this
def create_order(request):
orderformset = modelformset_factory(order, form=orderForm)
queryset = order.objects.none()
user = request.user
formset = orderformset(request.POST or None,queryset=queryset)
if formset.is_valid():
created=formset.save(commit=False)
created.User = request.user
created.save()
return redirect('home')
How i can give default user to this orders using modelformsets

In Your models file, use foreign key for user as follows
from django.contrib.auth import get_user_model
class order(models.Model):
name = models.CharField(max_length=300, null=True,)
description = models.CharField(max_length=300, null=True,blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
created_by = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
Then in your views wherever you handle GET request, intialize the form as such
def create_order(request, *args, **kwargs):
if request.method == 'GET':
initial = {'created_by':request.user}
form = orderform(initial=initial)
context['form'] = form
...
Then When you're handling the POST Request, just pass the POST and save it
def create_order(request, *args, **kwargs):
if request.method == 'POST':
form = orderform(request.POST)
if form.is_valid():
form.save()
...
This is How I'd handle This Scenario in django, Try out Class Based View. Its very good once you learn its abstract methods.
models.py
from django.contrib.auth import get_user_model
class Order(models.Model):
name = models.CharField(max_length=300, null=True,)
description = models.CharField(max_length=300, null=True,blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
created_by = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
forms.py
I Use hidden input to hide the input field, You can leave it open if you want. it will appear as a ChoiceField
from django import forms
from .models import Order
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = '__all__'
widgets = {
'created_by': forms.HiddenInput()
}
views.py
I use the Create view and override get initial method to pass user as initial value
from django.views.generic import CreateView
from .models import Order
class OrderCreateView(CreateView):
model = Order
form_class = OrderForm
template_name = 'order_create.html'
def get_initial(self):
initial = super().get_initial()
initial['created_by'] = self.request.user
return initial
order_create.html
...
<form method='POST'>
{{form}}
<button type="submit">Submit</button>
</form>
...

Related

How can I do username in reviews on django?

I'm doing reviews on django, but I want the user to not be able to enter any name. I want the username in the reviews to match the username of his profile
models.py
class Reviews(models.Model):
name = models.CharField('Имя', max_length=100)
text = models.TextField('Отзыв', max_length=3400)
parent = models.ForeignKey('self', verbose_name='Родитель', on_delete=models.SET_NULL, null=True, blank=True)
book = models.ForeignKey(BookModel, verbose_name='книга', on_delete=models.CASCADE)
name_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
views.py
class MoreInfoView(View):
""" """
def get(self, request, id):
book_info = BookModel.objects.filter(id=id).first()
stuff = get_object_or_404(BookModel, id=self.kwargs['id'])
total_likes = stuff.total_likes()
return render(request, 'bookapp/more_info.html', context={
'id': id,
'book_info': book_info,
'book': BookModel.objects.all(),
'total_likes': total_likes,
})
class AddReview(View):
"""Add Review"""
def post(self, request, pk):
form = ReviewForm(request.POST)
book = BookModel.objects.get(id=pk)
if form.is_valid():
form = form.save(commit=False)
form.book = book
form.save()
return HttpResponseRedirect(reverse('more_info', args=[pk]))
forms
class ReviewForm(forms.ModelForm):
class Meta:
model = Reviews
fields = ("name", "text", 'name_user')
You can add user manually after validating ReviewForm
I also added some changes(suggestions)
models.py
class Reviews(models.Model):
name = models.CharField('Имя', max_length=100)
text = models.TextField('Отзыв', max_length=3400)
parent = models.ForeignKey('self', verbose_name='Родитель', on_delete=models.SET_NULL, null=True, blank=True)
book = models.ForeignKey(BookModel, verbose_name='книга', on_delete=models.CASCADE, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True)
Setting blank=True makes the field optional.
views.py
class MoreInfoView(View):
""" """
def get(self, request, id):
book_info = BookModel.objects.filter(id=id).first()
stuff = get_object_or_404(BookModel, id=self.kwargs['id'])
total_likes = stuff.total_likes()
return render(request, 'bookapp/more_info.html', context={
'id': id,
'book_info': book_info,
'book': BookModel.objects.all(),
'total_likes': total_likes,
})
class AddReview(View):
"""Add Review"""
def post(self, request, pk):
user = request.user
# User has to be authenticated to create a review. And backend must
# validate it. You should raise PermissionDenied as response or
# redirect user to the login page, or something similar.
if not request.user.is_authenticated:
raise PermissionDenied()
form = ReviewForm(request.POST)
book = BookModel.objects.get(id=pk)
if form.is_valid():
form = form.save(commit=False)
form.book = book
form.user = user
form.save()
return HttpResponseRedirect(reverse('more_info', args=[pk]))
forms.py
class ReviewForm(forms.ModelForm):
class Meta:
model = Reviews
fields = ("name", "text")
I would advise to work with a CreateView [Django-doc] that will simplify a lot of the logic. You can implement this as:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
class AddReviewView(LoginRequiredMixin, CreateView):
form_class = ReviewForm
def get_success_url(self):
return reverse('more_info', args=[self.kwargs['pk']])
def form_valid(self, form):
form.instance.book_id = self.kwargs['pk']
form.name_user = self.request.user
return super().form_valid(form)
In your ReviewForm you thus remove the name_user as fields element.
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Note: You can limit views to a class-based view to authenticated users with the
LoginRequiredMixin mixin [Django-doc].
Note: normally a Django model is given a singular name, so Review instead of Reviews.
Note: Models normally have no …Model suffix. Therefore it might be better to rename BookModel to Book.

How to solve the NOT NULL constraint failed Error in Django

I am getting an IntegrityError when I want to save a new course on my e-learning website. Of course, I have searched for a similar solution on StackOverflow but I couldn't find an appropriate way for my solution.
here are my models
UserAccount Model
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserAccount(AbstractUser):
email = models.EmailField(
max_length=255, verbose_name='email', unique=True)
username = models.CharField(max_length=255, unique=True)
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
Course Model
from django.db import models
from accounts.models import UserAccount
class Course(models.Model):
owner = models.ForeignKey(
UserAccount, related_name='courses_created', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug = models.SlugField()
description = models.TextField()
cover_photo = models.ImageField(upload_to="cover/", null=True, blank=True)
Also, my course form is here
class CourseForm(forms.ModelForm):
class Meta:
model = Course
fields = ['curriculum', 'title', 'description', 'cover_photo']
widgets = {
'description': forms.Textarea(attrs={'rows': 3})
}
So in my view, I like to send the list of my courses to the template and also my CourseForm() using the get_context_data method. The code is bellow
My class-based view
class OwnerListMixin(object):
def get_queryset(self):
qs = super().get_queryset()
return qs.filter(owner=self.request.user)
class OwnerCourseMixin(OwnerListMixin, LoginRequiredMixin, PermissionRequiredMixin):
model = Course
fields = ['curriculum', 'title', 'description', 'cover_photo']
success_url = reverse_lazy('manage_course_list')
class ManageCourseListView(OwnerCourseMixin, ListView):
template_name = "courses_app/manage/course/list.html"
permission_required = "courses_app.view_course"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = CourseForm()
return context
but when I render the form in my template to save a new course I get the following Error
IntegrityError at /create/
NOT NULL constraint failed: courses_app_course.owner_id
CREATE VIEW
class CourseCreateView(OwnerCourseMixin, CreateView):
permission_required = "courses_app.add_course"
template_name = "courses_app/manage/course/form.html"
success_url = reverse_lazy("manage_course_list")
You need to set the user as the owner what currently is not happening. The form is being saved with the fields you have set. There are multiple ways of adding the user. You could do it this way.
from django.shortcuts import redirect
class CourseCreateView(OwnerCourseMixin, CreateView):
permission_required = "courses_app.add_course"
template_name = "courses_app/manage/course/form.html"
success_url = reverse_lazy("manage_course_list")
def form_valid(self, form):
instance = form.save(commit=False)
instance.owner = self.request.user
instance.save()
return redirect(self.get_success_url())

How to pass an argument in django templatetag or call form valid like in the views?

Hi Guys I want to add CreateView to be accessible all my web pages, so I opted for template tags, which bring out the form quite nicely but it can't save. I believe because of the user field which I want to be automatically added before saving the form. in Views.py is quite simple.
class BusinessCreate(LoginRequiredMixin, CreateView):
model = Business
form_class = BusinessAddForm
template_name = 'business/form.html'
def form_valid(self, form):
form.instance.user = self.request.user # this is what i want to add in templatetags
messages.success(self.request, 'successfully created your biashara')
return super().form_valid(form)
this is my form.py
class BusinessAddForm(ModelForm):
logo = forms.ImageField(label='', required=False, widget=forms.FileInput(attrs={'placeholder': 'your logo'}))
description = forms.Field(label='', widget=forms.Textarea(attrs={'placeholder': 'Describe your biashara'}))
name = forms.CharField(label='', widget=forms.TextInput(attrs={'placeholder': 'Your biashara name'}))
email = forms.EmailField(label='', required=True, widget=forms.TextInput(attrs={'placeholder': 'Email'}))
class Meta:
model = Business
fields = (
'name', 'logo', 'email', 'description')
Now I have a template tag
templatetags/business.py
from django.template import Library
from business.forms import BusinessAddForm
register = Library()
#register.inclusion_tag('includes/business_form.html', takes_context=True)
def get_business_form():
form = BusinessAddForm()
return {
'form': form,
}
which renders the form quite well but doesn't save. No errors though.
so where can I add the current logged in user to user Field?
my models.py
class Business(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = models.SlugField(max_length=200, blank=True, null=True)
user = models.ForeignKey(User, related_name='added_by', on_delete=models.PROTECT)
logo = models.ImageField(upload_to="business/logos", blank=True, null=True)
email = models.EmailField(help_text="This is required")
description = models.TextField(blank=True, null=True)
Thanks guys in advance

Trying to link two models with a ForeignKey but get the error "IntegrityError NOT NULL"

I have a model where a user posts a job vacancy, then other users can submit applications. The submit application model is called 'CandidatesSubmission' & pulls the 'title' from a different app/model 'JobPosts'.
I can add submit applications through the ADMIN page fine, but when trying to do so with a form I get "IntegrityError NOT NULL constraint failed: candidates_candidatessubmission.title_id."
I believe that I'm missing something in my Views.py that essentially says "use the title of job vacancy as the title field.
I have tried adding null=True, blank=False but which stops the error but the title isn't saved to the database.
Any suggestions on what I'm doing wrong would be great. Thank you
models.py
class CandidatesSubmission(models.Model):
title = models.ForeignKey('jobs.JobsPost', on_delete=models.CASCADE)
Fee = models.CharField(max_length=50, null=False, blank=False)
CandidateFirstName = models.CharField(max_length=50, null=True, blank=False)
CandidateSecondName = models.CharField(max_length=50, null=True, blank=False)
created = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.db.models import Q
from django.http import HttpResponseNotFound
from jobs.models import JobsPost
from candidates.models import CandidatesSubmission
from candidates.forms import CreateCandidatePostForm
from account.models import Account
from operator import attrgetter
# Create your views here.
def submit_candidates_view(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
form = CreateCandidatePostForm(request.POST or None, request.FILES or None)
if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(email=user.email).first()
obj.author = author
obj.save()
form = CreateCandidatePostForm()
context['form'] = form
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, 'candidates/submit_candidates.html', context)
def response_view(request):
context = {}
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, "candidates/response.html", context)
forms.py
from django import forms
from candidates.models import CandidatesSubmission
class CreateCandidatePostForm(forms.ModelForm):
class Meta:
model = CandidatesSubmission
fields = ['Fee', 'CandidateFirstName', 'CandidateSecondName']
def save(self, commit=True):
submission_post = self.instance
submission_post.Fee = self.cleaned_data['Fee']
submission_post.CandidateFirstName = self.cleaned_data['CandidateFirstName']
submission_post.CandidateSecondName = self.cleaned_data['CandidateSecondName']
if commit:
submission_post.save()
return submission_post
if you have "current" title, so your slug might store it, so you can use it like that.
def submit_candidates_view(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
form = CreateCandidatePostForm(post_slug=slug, request.POST or None, request.FILES or None)
if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(email=user.email).first()
obj.author = author
obj.save()
form = CreateCandidatePostForm()
context['form'] = form
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, 'candidates/submit_candidates.html', context)
in your forms.py we replace __init__ method to receive slug of your title
class CreateCandidatePostForm(forms.ModelForm):
class Meta:
model = CandidatesSubmission
fields = ['Fee', 'CandidateFirstName', 'CandidateSecondName']
def __init__(self, *args, **kwargs):
self.post_slug = kwargs.pop("post_slug", None)
super().__init__(*args, **kwargs)
def save(self, commit=True):
submission_post = self.instance
submission_post.title = JobsPost.objects.get(slug=self.post_slug)
if commit:
submission_post.save()
return submission_post

Query user in Django

first post here. Im trying to query the user so i from the form so i can save the user in my database.
This is my code
form = lageBruker(request.POST)
bruker = User.objects.create(format(request.POST['username']))
print()
if request.method == 'POST':
if form.is_valid():
fornavn = request.POST['first_name']
etternavn = request.POST['last_name']
email = request.POST['email']
kunde = Kunde.objects.create(
#bruker = bruker,
fornavn=fornavn,
etternavn=etternavn,
email=email
)
kunde.save()
context = {'form': form}
return render(request, 'ebutikk/registrer.html', context)
Kunde Model:
class Kunde(models.Model):
bruker = models.OneToOneField(
User, null=True, blank=True, on_delete=models.CASCADE)
fornavn = models.CharField(max_length=200, null=True, blank=True)
etternavn = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.etternavn
What im trying to do is, when the registration form is submittet, i want to save the registerd user as a kunde/customer. I dont have a User model, i use the default made by django with the import:
from django.contrib.auth.models import User
I make the form by importing the user creation form given by django and customizing it im my forms.py file.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class lageBruker(UserCreationForm):
class Meta:
model = User
fields = ['username',
'email',
'first_name',
'last_name',
'password1',
'password2']
Normally, you'd simply create the Kunde model like this:
class Kunde(models.Model):
bruker = models.OneToOneField(
User, null=True, blank=True, on_delete=models.CASCADE)
# more fields here, so the model makes sense
#property
def fornavn(self): return self.user.first_name
#property
def etternavn(self): return self.user.last_name
#property
def email(self): return self.user.email
Then all you need to do is:
def customer_signup_view(self, request):
if request.method == "POST":
form = lageBruker(request.POST)
# Saving the model form returns the user created
user = form.save()
# Now use that user to create a new customer
Kunde.objects.create(user=user)
return redirect("success/")
return render(request, 'ebutikk/registrer.html', {"form": lageBruker())

Categories