Automatically link form and user using OneToOneField - python

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()}

Related

Django: How to create a registration feauture in django without using the Django Usercreation Form?

I am trying to allow users create an account from without using the from django.forms import UserCreationForm. I just want the users to use just the input field and i can grab unto what ever they are passing into the input field and create an account for them.
This is the django forms for creating users with UserCreationForm, how do i now do the same but without the UserCreationForm?
views.py
def RegisterView(request):
if request.method == "POST":
form = UserRegisterForm(request.POST or None)
if form.is_valid():
new_user = form.save()
username = form.cleaned_data.get('email')
messages.success(request, f'Account Created')
new_user = authenticate(username=form.cleaned_data['email'],
password=form.cleaned_data['password1'],)
login(request, new_user)
return redirect('index')
elif request.user.is_authenticated:
return redirect('index')
else:
form = UserRegisterForm()
context = {
'form': form,
}
return render(request, 'userauths/sign-up.html', context)
forms.py
from django.contrib.auth.forms import UserCreationForm
from userauths.models import User
class UserRegisterForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
You can do this by creating your own user modelForm.
This will include multiple steps:
validate form
save form
set password using user.set_password() method.

Method to link logged Author to Article they created not working

Something is wrong with my method, assign_article_creator. It's supposed to populate the field, custom_user, with the username (email address) of the logged-in user/author, so that the author is associated with any article that they create. But it's not working. In Django Admin, the field custom_user is populated with '----' when an author creates an article. Please help me. Thank you.
models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
class Articles(models.Model):
custom_user = models.ForeignKey(CustomUser, default=None, null=True,
on_delete=models.SET_NULL)
views.py
class CreateArticle(LoginRequiredMixin, CreateView):
model = Articles
form_class = ArticleForm
template_name = "users/add_article.html"
def assign_article_creator(self, request):
if request.method == 'POST':
form = self.form_class(request, data=request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.custom_user = request.user
instance.save()
return render(request=request,
template_name ="users/add_article.html", context={"form":
form})
When you extend CreateView, you can't add just any method name you want to the class and expect it to work automatically. Instead, you need to override post() with the custom logic to assign custom_user. (You may want to name this author instead.) You can also leverage super().post() to do most of the work for you. Note that when you override post(), you don't need if request.method == 'POST': because CreateView already does that for you.

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

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 claas Admin 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)
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.

Categories

Resources