Im extending the django User model with User profile like this :
class UserProfile(BaseModel):
user = models.ForeignKey(User, unique=True, related_name="profile")
city = models.CharField(_("City"), max_length=200)
tel = models.CharField(_("Phone Number"), max_length=50,
help_text=_("(+ Country Code) (Area Code) (Your phone number)"))
description = models.TextField(null=True, blank=True,
help_text = _("Small description about yourself."))
photo = models.ImageField(max_length=255, upload_to="profiles/")
def __unicode__(self):
return "%s %s" % (self.user.first_name, self.user.last_name)
def profile_image(self):
return settings.DEFAULT_PROFILE_IMAGE
and this is the form Im using on the front end in order to edit the profile from there:
class UserProfileForm(forms.ModelForm):
# uniForm Helper
helper = FormHelper()
helper.form_id = "edit_profile_form"
helper.form_class = 'mlForm'
layout = Layout(
Fieldset('',
'country', 'city',
'tel', 'photo', 'description',
)
)
helper.add_layout(layout)
# Submit button(s)
submit = Submit('submit','Submit')
helper.add_input(submit)
cancel = Submit('cancel','Cancel')
helper.add_input(cancel)
class Meta:
model = UserProfile
fields = ['city',
'tel', 'photo', 'description',]
def __init__(self, request, *args, **kw):
super(UserProfileForm, self).__init__(*args, **kw)
self.request = request
def save(self, *args, **kw):
edit_profile_form = super(UserProfileForm, self).save(*args, **kw)
return edit_profile_form, "User successfully modified."
What I want to do is add the User email field in the form so that the user can also edit this field from the frontend.
How would I do that?
Hope, this will help
class UserProfileForm(forms.ModelForm):
email = forms.EmailField(label=u'Email address',required=True)
class Meta:
model = UserProfile
exclude = ['user',]
def __init__(self, *args, **kw):
super(UserProfileForm, self).__init__(*args, **kw)
self.fields['email'].initial = self.instance.user.email
self.fields.keyOrder = ['your','fields','you','want','to','display','including','email']
def save(self, *args, **kw):
super(UserProfileForm, self).save(*args, **kw)
self.instance.user.email = self.cleaned_data.get('email')
self.instance.user.save()
this recipe works for me (django 1.3).
in views.py must be something like this:
def profile(request,id):
if request.method == 'POST':
user = get_object_or_404(User,pk=id)
profile = user.profile
form = UserProfileForm(data = request.POST,instance = profile)
if form.is_valid():
form.save()
Send the two objects-forms (UserEditForm and UserProfileForm) into the template form and submit them together.
Related
class Book(models.Model):
description = models.CharField(max_length=10)
pdf = models.FileField(upload_to='books/pdfs/')
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.description
def delete(self, *args, **kwargs):
self.pdf.delete()
super().delete(*args, **kwargs)
#forms.py
class BookForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(BookForm, self).__init__(*args, **kwargs)
class Meta:
model = Book
fields = ('description', 'pdf', 'user')
When i run an application it shows all the users, I want to restrict to only current user who is logged in.
I have a model StaffProfile.while creating a form for Visiti want to get staff_user data(Based on current user) to that ChoiceField (to_meet).
models.py
class StaffProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
related_name="user_profile")
staff_user = models.ManyToManyField(User, null=True, blank=True,
related_name="staff_user")
class Visit(models.Model):
name = models.CharField(max_length=200, name="name")
gender = models.CharField(choices=GENDER_CHOICE, max_length=1, name="gender")
mobile = models.CharField(max_length=18, default="", name="mobile")
to_meet = models.ForeignKey(User, on_delete=models.CASCADE)
forms.py
class VisitForm(forms.ModelForm):
to_meet = forms.ChoiceField(choices=[], required=False, label="Select Staff")
class Meta:
model = Visit
fields = ("__all__")
def __init__(self, *args, **kwargs):
super(VisitForm, self).__init__(*args, **kwargs)
self.fields['to_meet'].choices = StaffProfile.objects.filter(user=request.user).values_list("staff_user")
Initially override the __init__() method of your view
class VisitForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(VisitForm, self).__init__(*args, **kwargs)
self.fields['to_meet'].choices = [self.request.user]
to_meet = forms.ChoiceField(choices=[], required=False, label="Select Staff")
class Meta:
model = Visit
fields = "__all__" # small typo here
Then, in your view,
def foo_view(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = VisitForm(request.POST,request=request)
# check whether it's valid:
if form.is_valid():
# do somrthing
.....
You need to pass the request from view to form. For example:
def some_view(request):
form = VisitForm(request=request)
# rest of the code
and use it in the form:
def __init__(self, *args, **kwargs):
request = kwargs.pop('request')
super(VisitForm, self).__init__(*args, **kwargs)
self.fields['to_meet'].choices = StaffProfile.objects.filter(user=request.user).values_list("staff_user")
I wrote my own form for editing of profile and need to save ip of user, who edit profile, but not really understand how to do this. I know, that ip we can get from request.META['REMORE_ADDR'] but where to put this and how to save to my db... Will be very glad if you could help.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, unique=True)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
date_of_birth = models.DateField()
biography = models.TextField()
contacts = models.CharField(max_length=200)
ip_address = models.GenericIPAddressField(null=True)
forms.py
class UserEditProfile(forms.ModelForm):
first_name = forms.CharField( max_length=30)
last_name = forms.CharField( max_length=30)
date_of_birth =
forms.DateField(widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES))
biography = forms.Textarea()
contacts = forms.CharField()
def __init__(self, *args, **kw):
super(UserEditProfile, self).__init__(*args, **kw)
self.fields['first_name'].initial = self.instance.first_name
self.fields['last_name'].initial = self.instance.last_name
self.fields['date_of_birth'].initial =
self.instance.date_of_birth
self.fields['biography'].initial = self.instance.biography
self.fields['contacts'].initial = self.instance.contacts
self.fields.keyOrder = [
'first_name',
'last_name',
'date_of_birth',
'biography',
'contacts'
]
def save(self, *args, **kw):
super(UserEditProfile, self).save(*args, **kw)
self.instance.first_name = self.cleaned_data.get('first_name')
self.instance.last_name = self.cleaned_data.get('last_name')
self.instance.date_of_birth =
self.cleaned_data.get('date_of_birth')
self.instance.biography = self.cleaned_data.get('biography')
self.instance.contacts = self.cleaned_data.get('contacts')
self.instance.save()
class Meta:
model = Profile
fields = (
'first_name',
'last_name',
'date_of_birth',
'biography',
'contacts'
)
exclude = ['user', 'ip_address']
view.py
def edit_profile(request):
user = Profile.objects.get(id=request.user.id)
if request.method == "POST":
form = UserEditProfile(request.POST, instance=user)
if form.is_valid():
form.save(commit=False)
return redirect('profile')
else:
form = UserEditProfile(instance=user)
args = {'form': form}
return render(request, 'edit.html', args)
You cannot pass request object into form directly. That's not the way it works. If you need to associate any request attributes to your model instances, you should do it in the views.
You could collect the request.META['REMOTE_ADDR'] which gives the IP info of the logged in user in the view and associate it to yourinstance` in the view itself.
You could do this in your form.is_valid() method,
if form.is_valid():
profile = form.save(commit=False)
profile.ip_address = request.META['REMOTE_ADDR']
profile.user = request.user
profile.save()
return redirect('profile')
Simply asked: In a form, how do you restrict the display of a many-to-many relationship to the records the user has defined himself?
In an effort to keep things as DRY as possible, I'm using forms.ModelForm.
Here in Example, a user can create feed-items which run on a schedule. Technically the feeds and the items are connected to the user by user = models.ForeignKey(User) however that in itself is not enough to restrict the association of the two through the user himself.
While I'd love to inherently restrict association of the two THROUGH the user, I'd be happy to simply restrict the display of the items via user and simply validate afterwards. Example data below:
class Example(models.Model):
global CHOICES_DAYS
global CHOICES_HOURS
user = models.ForeignKey(User)
label = models.CharField(max_length=180)
title = models.CharField(max_length=1000, blank=True)
content = models.TextField(max_length=10000, blank=True)
Example_feeds = models.ManyToManyField(ExampleFeed, blank=True)
hourly_schedule = models.CharField(choices=CHOICES_HOURS, max_length=2, default=4)
weekly_schedule = models.CharField(choices=CHOICES_DAYS, max_length=5, default=1)
last_used = models.DateTimeField(default=timezone.now, blank=False)
def __str__(self):
return self.label
class Meta:
ordering = ('last_used',)
And here is the form, of which I'm using forms.ModelForm to keep things as DRY as possible:
class ExampleForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.helper = FormHelper()
self.helper.form_id = ''
self.helper.form_class = ''
self.helper.form_method = 'post'
self.helper.add_input(Submit('submit', 'Submit'))
super(ExampleForm, self).__init__(*args, **kwargs)
class Meta():
model = Example
fields = [
'label',
'title',
'content',
'example_feeds',
'hourly_schedule',
'weekly_schedule']
You need to pass the request.user to the form when you are instantiating it in your view and then make use of that request object to restrict the form field's queryset.
class ExampleForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
super(ExampleForm, self).__init__(*args, **kwargs)
self.fields['mym2mfield'].queryset = Example.objects.filter(example_feeds__user=request.user)
and in your view (assuming it's a class based view):
class MyView(FormView):
def get_form(self, form_class):
return form_class(self.request, self.get_form_kwargs())
I need add the first_name and last_name fields associated with
that User model and display it in the profile form.
fields:
>>> user = User.objects.get(pk=1)
>>> user.first_name
u'Some'
>>> user.last_name
u'User'
My model is something like this :
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
personal_email = models.EmailField(blank=True)
address = models.CharField(max_length=140)
phone_number = models.CharField(max_length=20)
def __unicode__(self):
return u'Profile of user: %s' % self.user.username
when rendering the profile form, would have to show the fields.
first_name:
last_name:
personal_email:
address:
phone_number:
Edit
I resolved to:
#forms.py
class UserProfileForm(forms.ModelForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
self.fields['first_name'].initial = self.instance.user.first_name
self.fields['last_name'].initial = self.instance.user.last_name
self.fields.keyOrder = [
'first_name',
'last_name',
'personal_email',
'address',
'phone_number',
]
def save(self, *args, **kwargs):
super(UserProfileForm, self).save(*args, **kwargs)
self.instance.user.first_name = self.cleaned_data.get('first_name')
self.instance.user.last_name = self.cleaned_data.get('last_name')
self.instance.user.save()
class Meta:
model = UserProfile
#urls.py
url(r'^profiles/edit/', edit_profile, {'form_class': UserProfileForm},
name='profiles_edit_profile' ),
and add in #signals.py
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
userprofile, new = UserProfile.objects.get_or_create(user=instance)
Assuming you are using a ModelForm you could do the following:
class profileForm(ModelForm):
first_name = forms.CharField(max_length=30, required=False)
last_name = forms.CharField(max_length=30, required=False)
class Meta:
model = UserProfile
def save(self, commit=True):
m = super(customerForm, self).save(commit=False)
# Update and save user model here
if commit:
m.save()
return m
You could skip overriding the save methods and do the save in your view. Just get get the first and last name value and save it after you validate the form. You might also want to used a transaction to make sure everything saves or nothing does.