Django claas Admin auto-populate user field - python

I am trying to populate the field 'owner' in the my NoteForm. I read in documentation that I need to use the Admin for that.But i still get this error : note_note.owner_id may not be NULL. Need help.
Code:
forms.py:
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ('title','body')
models.py:
class Note(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
cr_date = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, blank=False)
class NoteAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
form.owner = request.user
form.save()
views.py:
def create(request):
if request.POST:
form = NoteForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponceRedirect('/notes/all')
else:
form = NoteForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_note.html', args)
i also tried to write the class NoteAdmin in admin.py , just in case. Same error.What i am doing wrong? I am just following the documentation.

You are trying to save Note without owner field and the error said it. Try like:
if form.is_valid():
obj = form.save(commit=False)
obj.owner = request.user
obj.save()
The other way is to set null=True for the owner field if you can write data without owners.

Related

Creating and updating Model object using form

models.py
class PostModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date_time = models.DateTimeField(auto_now_add=True)
title = models.TextField(null=True)
body = models.TextField(null=True)
def __str__(self):
return str(self.user)
class ImagesPostModel(models.Model):
post = models.ForeignKey(PostModel, on_delete=models.CASCADE)
images = models.ImageField(null=True, blank=True)
views.py
def post(request):
post = PostModel(user=request.user)
post.save()
if request.method == 'POST':
form = PostModelForm(request.POST, instance=post)
images = request.FILES.getlist('images')
for image in images:
ImagesPostModel.objects.create(post=post, images=image)
if form.is_valid():
form.save()
return redirect('/Blog/home/')
else:
form = PostModelForm(request.POST)
return render(request, 'post.html', {'form': form})
I created a PostModel object post and save it in the database using save() method. I have provided the instance parameter as post object in the form, so the form should be updating the above created post but it is creating another PostModel object and inserting into the database by itself. So there are two post begin created and being inserted into the database, first one is because of post = PostModel(user=request.user) and I dont know why the second one is being created.
why is this happening?
The problem is the first 2 lines in the view
post = PostModel(user=request.user)
post.save()
As they create a PostModel obj with user=currentuser
To add the post to the user do the following rather than form.save()
post = form.save(commit=False)
post.user = request.user
post.save()

Can someone help? Sending notifications to all users or some users in django forms

I want to send a single notification message to multiple users or all users. I have tried many to many fields but the sent to id won't save the i.d's of the users that i have sent the message to.
Models.py
class Notifications(models.Model):
id=models.AutoField(primary_key=True)
sent_to = models.ManyToManyField(CustomUser)
message = models.TextField(null=True)
message_reply = models.TextField(null=True)
created_at=models.DateTimeField(auto_now_add=True)
updated_at=models.DateTimeField(auto_now=True)
Views.py
def add_notification(request):
notifs = Notifications.objects.all()
users = CustomUser.objects.filter(is_staff=True)
if request.method == 'POST':
form = AddNotifForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.message_reply = "none"
instance.save()
sent_to = form.cleaned_data.get('sent_to')
messages.success(request, f'Message has been successfully sent .')
return redirect('add_notif')
else:
form = AddNotifForm()
context={
'notifs' : notifs,
'form' : form,
'users' : users,
}
template_name ='main-admin/add-notif.html'
return render(request, template_name, context)
Forms.py
class AddNotifForm(forms.ModelForm):
sent_to = forms.ModelMultipleChoiceField(
queryset=CustomUser.objects.filter(is_staff=True).exclude(is_superuser=True),
widget=forms.CheckboxSelectMultiple,
required=True)
class Meta:
model = Notifications
fields = ['sent_to', 'message']
From the docs:
every time you save a form using commit=False, Django adds a save_m2m() method to your ModelForm subclass. After you’ve manually saved the instance produced by the form, you can invoke save_m2m() to save the many-to-many form data.
So you'll have to call save_m2m() after instance.save() if you are using commit=False:
instance = form.save(commit=False)
instance.message_reply = "none"
instance.save()
form.save_m2m() # <-- Add this

Automatically link form and user using OneToOneField

I have create a model form using also OneToOneField field to link it to my user, my problem is that I have to go to the admin section to manually select the user to make it works. Is it possible to have the user linked to the form submitted automatically?
Also this may be stupid but when I use user.userinformation.gender to get the info about gender I get back "m", is there a way to access the label "Male" instead? TThank for yours help!
My code:
models.py
class UserInformation(models.Model):
gender_choice = [('m', 'Male'),('f', 'Female')]
user = models.OneToOneField(User, blank=True, null=True, on_delete=models.CASCADE)
first_name = models.CharField(max_length=120)
last_name = models.CharField(max_length=120)
gender = models.CharField(max_length=120, choices=gender_choice)
phone = models.CharField(max_length=10)
email = models.EmailField()
forms.py
class UserInformationForm(forms.ModelForm):
class Meta:
model = UserInformation
fields = ('first_name', 'last_name', 'gender', 'phone', 'email',)
views.py
def add_information(request):
if request.method == "POST":
form = UserInformationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Form submitted')
else:
form = UserInformationForm()
return render(request, 'accounts/profile/add_information.html', {'form': form})
def show_profile(request):
profile_info = UserInformation.objects.all()
return render(request, 'accounts/profile/user_profile.html', {'profile_info': profile_info})
Yes, you can link the .user of the UserInformation to the logged in user with:
from django.shorcuts import redirect
from django.contrib.auth.decorators import login_required
#login_required
def add_information(request):
if request.method == 'POST':
form = UserInformationForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
messages.success(request, 'Form submitted')
return redirect('name-of-some-view')
else:
form = UserInformationForm()
return render(request, 'accounts/profile/add_information.html', {'form': form})
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
I think that what you are looking for is the initial attribute of UserInformationForm instance but you need to add user to the form fields.
form = UserInformationForm(initial={"user":request.user.id})
If you dont want your user to see/edit the information, consider using a HiddenInput widget in your ModelForm or set disabled attribute.
class UserInformationForm(forms.ModelForm):
class Meta:
model = UserInformation
fields = '__all__'
widgets = {'user': forms.HiddenInput()}

How to populate my Django Model 'updated_by' field with logged in User automatically using a formset?

I am a beginner with Django and I have been enjoying it so far. I figured out how to use model formsets, but I cannot figure out how to make my form automatically use logged in User as the 'updated_by' field.
models.py
class Inventory(models.Model):
item = models.CharField(max_length=50, unique=True)
stock = models.IntegerField()
par = models.IntegerField()
date_updated = models.DateTimeField(auto_now=True)
updated_by = models.ForeignKey(User, on_delete=models.PROTECT)
def __str__(self):
return self.item
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
phone = PhoneField(blank='True', help_text='Contact Phone Number')
def __str__(self):
return f'{self.user.username} Profile'
def save(self):
super().save()
I think the problem lies in your views.py. Try getting request.user before saving the form.
i think you should have made form for Inventory if yes(let InvntoryForm) than in view.py file you have done something like this:-
if request.method == 'POST':
Inven_form=InventoryForm(data=request.POST)
if Inven_form.is_valid():
user=Inven_form.save()
#in between add this
Inven_form.updated_by=request.user.username
user.save()
I would use the 'commit=False' argument which will create a new object and assign it without saving to your database. You can then set the user attribute and call save() with no arguments.
For example, this is how I assigned the user attribute to my blog app.
in views.py
if form.is_valid():
# Create a new entry and assign to new_article.
new_article = form.save(commit=False)
# Set the new article attribute to the current user.
new_article.user = request.user
# Save to database now the object has all the required data.
new_article.save()
Here is the full code for the add_article view if this helps.
#login_required
def add_article(request):
""" Add a new article. """
if request.method != 'POST':
# No data submitted, create a blank form.
form = AddArticleForm()
else:
# POST data submitted, process data.
form = AddArticleForm(request.POST, request.FILES)
if form.is_valid():
new_article = form.save(commit=False)
new_article.author = request.user
new_article.save()
return back_to_blog_page()
context = {'form': form}
return render(request, 'add_article.html', context)

Django Admin class to auto-populate user field

I am trying to populate the field 'owner' in the my NoteForm. I read in documentation that I need to use the Admin for that.But i still get this error : note_note.owner_id may not be NULL. Need help. Code:
forms.py:
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ('title','body')
models.py:
class Note(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
cr_date = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, blank=False)
admin.py
class NoteAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj = form.save(commit=False)
obj.owner = request.user
obj.save()
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
else:
fromset.save_m2m()
admin.site.register(Note, Noteadmin)
views.py:
def create(request):
if request.POST:
form = NoteForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponceRedirect('/notes/all')
else:
form = NoteForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_note.html', args)
I do not understand the point of Admin over here. From the code, what I understood is you creating a simple django form for your site and getting the error on form submission. If that's case, the solution is quiet easy. This error is generated because you are try to save a record in your Note model without any reference to User. As there's a db constraint on the foreign key field, it raises the error. Solution is easy, just add owner to the list of fields in the form or modify the save method to assign an owner to the note. If you'll use the first option, the user will be able to see and select the owner. And if you want to pre-populate that particular field, pass initial value to the form.

Categories

Resources