I am new in Django and I really need help,
I do not know how to save my form data to database. I have problem to views.py
I will user's id who filled the form added into the foreign key field.
If there is any link or example that help me I appreciate you.
# views.py
#login_required(login_url="home")
def melk_new(request):
form = MelkForm()
???
return render(request, 'melk_new.html',{'form': form})
# models.py
class Melk(models.Model):
category = models.CharField(max_length=50)
city = models.CharField(max_length=100)
person = models.ForeignKey('CustomUser', on\_delete=models.CASCADE)
def \_\_str\_\_(self):
return self.category
class CustomUser(AbstractUser):
def __str__(self):
return self.email
---------------------------------------------------------------------------
# forms.py
class MelkForm(forms.ModelForm):
class Meta:
model = Melk
fields = ('category', 'city')
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'email')
To get the currently logged in user you'll find it within request.user object. but before you assume that there is a currently logged in user, you need to validate that so you have 2 widely known options:
request.user.is_authenticated()
#login_required() decorator used if you from django.contrib.auth.decorators import login_required
if request.user.is_authenticated():
Car.objects.create(model_id=some_id, person=request.user)
Note:
The #login_required() is added above the function
#login_required(login_url="home")
def melk_new(request):
form = MelkForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.user_id = request.user.id
instance.save()
return render(request,'melk_new.html', { 'form': form})
Related
I want to create a PostModel(just like instagram) and while the form is created to connect the user to the model with One-to-one/foreign key relationship, anyway I'm getting a problem while trying to upload an image and the db doesn't updates.
I've tried this solution
...
# models.py
from django.contrib.auth.models import User
from django.conf import settings
class Post(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
description = models.CharField(max_length=255, blank=True)
image = models.ImageField(upload_to='images')
uploaded_at = models.DateTimeField(auto_now_add=True)
...
# forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('description', 'image', )
def save(self, commit=True):
if commit:
Post.save()
return Post
...
# views.py
def account(request):
post = PostForm(request.POST, request.FILES)
if request.method == "POST":
if post.is_valid():
post.save(commit=False)
post.owner = request.user
post.save(commit=True)
messages.success(request, f"you had successfully updated your profile image")
return redirect("main:account")
else:
for msg in form.error_messages:
messages.error(request, f"{msg}: {form.error_messages[msg]}")
return render(request = request,
template_name = "main/account.html",
context={'PostForm':post})
post = PostForm()
return render(request = request,
template_name = "main/account.html",
context={'PostForm':post})
You should not override the def save() method, this is fine as it is now, so:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('description', 'image', )
# no save
as for the view, you need to add the owner to the object, but here you are adding it to the form, and that thus has no effect (on the object):
from django.contrib.auth.decorators import login_required
#login_required
def account(request):
post = PostForm(request.POST, request.FILES)
if request.method == 'POST':
if post.is_valid():
post.instance.owner = request.user
post.save()
messages.success(request, f'you had successfully updated your profile image')
return redirect('main:account')
# …
I would also advise to rename post to post_form, since this is a form, not a post object.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
i want to auto insert user to the follwing model:
class Moduls(models.Model):
module_name = models.CharField(max_length=255)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column='created_by', blank=False, null=False , on_delete=models.CASCADE, editable = False)
i have 2 cases :
1- in django admin and i solve this case by the following
* add editable = False to created by field
* in admin.py i used the follwoing:
def save_model(self, request, obj, form, change):
obj.created_by = request.user
super().save_model(request, obj, form, change)
but i face the problem when i try to use forms.py i can't pass user from user views.py and if i want to add created_by field to my form i have this error:
'created_by' cannot be specified for Moduls model form as it is a non-editable field
You normally do not set that in the form, but in the view. So you define a form that looks like:
class ModulsForm(forms.ModelForm):
class Meta:
model = Moduls
fields = ['module_name']
In the view, you then set the created_by field of the instance wrapped in the view. So for a function-based view, it looks like:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def some_view(request):
if request.method == 'POST':
form = ModulsForm(request.POST, request.FILES)
if form.is_valid():
form.instance.created_by = request.user
form.save()
return redirect('name-of-some-view')
else:
form = ModulsForm()
return render(request, 'name-of-some-template.html', {'form': form})
or in a class-based view, for example a CreateView, you override the form_valid method:
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
class ModulsCreateView(LoginRequiredMixin, CreateView):
model = Moduls
form_class = ModulsForm
# …
def form_valid(self, form):
form.instance.created_by = self.request.user
return super().form_valid(form)
I am extending User model to add profile information using onetoone relation. The user should be able to change the basic user profile info.
What should be the views to add such functionality?
Here is my model
Models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
description = models.CharField(max_length=100, default='No description field')
city = models.CharField(max_length=100, default='Location not added')
phone = models.CharField(max_length=10, default='',blank= True)
image = models.ImageField(upload_to='products/profile/%Y%/%m/%d', blank=True)
def __str__(self):
return self.user.username
Here is my form
forms.py
class UserForm(forms.ModelForm):
class Meta():
model = UserProfile
fields = ['description', 'city', 'phone', 'image']
What should I include in my views?
views.py
#login_required()
def edit_profile(request):
pass
I want to update the model the extended UserProfile instance in a way that the previous info gets overwritten and the new information is updated.
You need to handle the UserForm in the view like any other usual form.
here what you need to do:
views.py
def edit_profile(request):
if request.method == 'POST':
# don't forget to pass request.FILES since you have imageField
form = UserForm(request.POST,
request.FILES,
instance=request.user.userprofile)
if form.is_valid():
form.save()
return redirect(reverse('to_user_profile_url'))
else:
form = UserForm(instance=request.user.userprofile)
context = {'form': form}
return render(request, 'edit_profile_template', context)
I want to get request as a parameter in save() method.
models.py
class Profile(models.Model):
uuid = UUIDField(auto=True)
user = models.ForeignKey(User)
name = models.CharField(max_length=128)
dob = models.DateField()
class Meta:
db_table = 'profile'
def save(self,*args,**kwargs):
if not self.pk:
self.user_id = 2 #here i need request.user instead of 2
super(Profile,self).save(*args,**kwargs)
forms.py
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
exclude = ['uuid','user']
views.py
def add(request):
profile_form = ProfileForm(request.POST)
profile_form.save()
Instead of the value 2 i want to pass request.user. How can i do it. If question is not correct somebody please correct the question.
Don't do that in the model. Do it in the view.
profile_form = ProfileForm(request.POST)
if profile_form.is_valid():
profile = profile_form.save(commit=False)
profile.user = request.user
profile.save()
One way is to use crequest, like this:
# model
from crequest.middleware import CrequestMiddleware
class Profile(models.Model):
# Some fields
def save(self, *args, **kwargs):
crequest = CrequestMiddleware.get_request() #its the current request
if crequest.user.pk is 1:
# Do stuff
pass
super(Profile,self).save(*args,**kwargs)
You can use kwargs.
For example:
views.py
profile_form.save(your_arg = request)
models.py
your_var = kwargs.pop("your_arg", None) #Second argument of kwargs.pop is default value
In you case, pass request as keyword argument, and then use it in models save() method.
I am trying to allow users to be able to create and edit their profiles once they have registered. I am using a model form. What I need to do is have the employer model field be filled with the current user.
Here is my view:
def update_profile(request, username):
if request.method == 'POST':
edit_profile_form=EditProfileForm(request.POST)
if edit_profile_form.is_valid():
editprofile = edit_profile_form.save(commit=False)
editprofile.employer = request.user.get_profile()
editprofile.save()
edit_profile_form = EditProfileForm()
context = {'edit_profile_form':edit_profile_form,}
return render(request, 'pandaboard/editprofile.html', context)
Here is my model:
class Profile(models.Model):
employer = models.ForeignKey(User)
company_name = models.CharField(max_length=100)
company_description = models.TextField()
company_website = models.URLField(max_length=200, blank=True)
contact_email = models.EmailField(max_length=100)
contact_name = models.CharField(max_length=100)
def __unicode__(self):
return self.company_name
Here is my Model Form
from django.forms import ModelForm
from pandaboard.models import JobPost, Profile
from django.contrib.auth.models import User
class EditProfileForm(ModelForm):
class Meta:
model = Profile
fields = ['company_name','company_description','company_website','contact_email','contact_name']
To hydrate your form with values from your existing model instance, you need to use the instance argument on the model form:
def update_profile(request, username):
profile = request.user.get_profile()
edit_profile_form = EditProfileForm(request.POST or None,
current_user=request.user, instance=profile)
if request.method == 'POST':
if edit_profile_form.is_valid():
editprofile.save()
context = {'edit_profile_form': edit_profile_form}
return render(request, 'pandaboard/editprofile.html', context)
To inject the current request.user, you can override the __init__ of EditProfileForm, passing in an extra keyword argument (or arg, it doesn't really matter), and the popping it out of the kwargs before calling super so you aren't passing the ModelForm a keyword argument it isn't expecting:
class EditProfileForm(ModelForm):
class Meta:
model = Profile
def __init__(self, *args, **kwargs):
current_user = kwargs.pop('current_user')
super(EditProfileForm, self).__init__(*args, **kwargs)
self.fields['employer'] = current_user
Now you don't have to pass commit=False and manually set the value of employer in the view.