How to get requested user in clean function in django forms? - python

Well i want to get requested user in clean function of django forms but i'm unable to do that. I'm trying to get that by simply saying self.request.user , it works in views but not working in forms.py, anybody have an idea how to get requested user in djnago forms ?
forms.py
class KycModelForm(forms.ModelForm):
class Meta:
model = KycModel
fields = '__all__'
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(KycModelForm, self).__init__(*args, **kwargs)
def clean(self):
cleaned_data = super().clean()
user = User.objects.get(username=self.request.user)
print(user)
views.py
class KycFormCreateView(CreateView):
form_class = KycModelForm
model = KycModel
template_name = "accounts/kyc/new_kyc.html"
def form_valid(self, form):
user_kyc = form.save(commit=False)
user_kyc.owner = self.request.user
user_kyc.save()
return super().form_valid(form)

You never construct a form with a request in the first place. You should pass this with:
class KycFormCreateView(CreateView):
form_class = KycModelForm
model = KycModel
template_name = 'accounts/kyc/new_kyc.html'
def get_form_kwargs(self, *args, **kwargs):
form_kwargs = super().get_form_kwargs(*args, **kwargs)
form_kwargs['request'] = self.request
return form_kwargs
def form_valid(self, form):
user_kyc = form.save(commit=False)
user_kyc.owner = self.request.user
user_kyc.save()
return super().form_valid(form)
In the clean function, you do not need to query for a user self.request.user is a user object, so you can work with self.request.user directly:
class KycModelForm(forms.ModelForm):
class Meta:
model = KycModel
fields = '__all__'
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(KycModelForm, self).__init__(*args, **kwargs)
def clean(self):
cleaned_data = super().clean()
user = self.request.user
print(user)
return cleaned_data

Related

How to get data from forms?

How can I get data from a form (ProductCreateForm)?
If I write form = self.get_form(), then I just get a form template, where some data is selected, and some are not (select especially).
If I write form = ProductCreateForm(request.POST), then I get an error saying that the request was not found. Perhaps this is due to the fact that I set the request in get_context_data() and work with them in the __init__ method in the forms.py.
I process the data in the clean method in the forms.py.
I have the following view
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
http_method_names = ['get', 'post']
def get_initial(self):
initial = super(ProductsCreate, self).get_initial()
initial['request'] = self.request
return initial
​
def get_context_data(self, *args, **kwargs):
ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
​
def get(self, request, *args, **kwargs):
self.object = None
if kwargs.get('slug'):
category = Category.objects.filter(slug=kwargs.get('slug')).first()
self.initial.update({'category': category})
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = ProductCreateForm(request.POST) #What here?
special_form = SpeciallyPriceForm(self.request.POST)
​
if form.is_valid() and special_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
forms
class ProductCreateForm(forms.ModelForm):
#....
​
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('initial').get('request')
super(ProductCreateForm, self).__init__(*args, **kwargs)
#...
user = self.request.user
provider = Provider.objects.filter(user=user.id).last()
self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all())
#...
def clean(self):
cleaned_data = super(ProductCreateForm, self).clean()
cd_category = cleaned_data.get('category')
#...
​
​
class SpeciallyPriceForm(forms.ModelForm):
class Meta:
model = SpeciallyPrice
fields = ['adittional_specially_price', 'adittional_specially_number']
1.try pass request in that way
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
initial = super(ProductsCreate, self).get_initial()
initial['request'] = self.request
return initial
then in forms.py
def __init__(self):
kwargs.pop('initial').get('request')
Are you sure that is working at all? On init in your forms I don't see super() call so you should get an error?
Do you have problem only with category field the rest data you get properly?
Where do you pass it kwargs.pop('request') ??
You can print and check what is in self.request.POST

in django CreateView, how do I add field and send that field as a context to template?

I know this is very beginner question but I still don't get it even after I read https://docs.djangoproject.com/en/1.9/ref/class-based-views/generic-editing/
so I have this createView right...
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'main/add_post.html'
def form_valid(self, form):
self.object = form.save(commit=False)
# any manual settings go here
self.object.moderator = self.request.user
self.object.image = extract(self.object.url)
self.object.thumbnail = extractt(self.object.content)
self.object.save()
return HttpResponseRedirect(reverse('post', args=[self.object.slug]))
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(PostCreateView, self).dispatch(request, *args, **kwargs)
and in add_post.html I want to use
hotCat = Category.objects.get_hotCat()
how do I use that hotCat in add_post.html?
You add variables into the context by overriding the get_context_data() method.
def get_context_data(self, **kwargs):
ctx = super(PostCreateView, self).get_context_data(**kwargs)
ctx['hotCat'] = Category.objects.get_hotCat()
return ctx

django update view and passing context

I have a update view:
class GeneralUserUpdateView(UpdateView):
model = GeneralUser
form_class = GeneralUserChangeForm
template_name = "general_user_change.html"
def dispatch(self, *args, **kwargs):
return super(GeneralUserUpdateView, self).dispatch(*args, **kwargs)
def post(self, request, pk, username):
self.pk = pk
self.username = username
self.gnu = GeneralUser.objects.get(pk=self.pk)
#form = self.form_class(request.POST, request.FILES)
return super(GeneralUserUpdateView, self).post(request, pk)
def form_valid(self, form, *args, **kwargs):
self.gnu.username = form.cleaned_data['username']
self.gnu.email = form.cleaned_data['email']
self.gnu.first_name = form.cleaned_data['first_name']
self.gnu.last_name = form.cleaned_data['last_name']
self.gnu.address = form.cleaned_data['address']
self.gnu.save()
return redirect("user_profile", self.pk, self.username)
Here in this view I want to pass a context like:
context['picture'] = GeneralUser.objects.get(pk=self.pk)
I did trying get_context_data but I cant access pk in there..
Am I doing the update right?? How can I pass that context in there??
You shouldn't be overriding post at all. All of that logic should happen in get_context_data.
In fact, none of your overrides are needed. Everything that you do in form_valid will be done already by the standard form save. And overriding dispatch just to call the superclass is pointless.
Your view should look like this only, with no overridden methods at all:
class GeneralUserUpdateView(UpdateView):
model = GeneralUser
form_class = GeneralUserChangeForm
template_name = "general_user_change.html"
context_object_name = 'picture'
(although it seems a little odd that you want to refer to an instance of GeneralUser as "picture").
Edit to redirect to a specific URL, you can define get_success_url:
def get_success_url(self):
return reverse("user_profile", self.kwargs['pk'], self.kwargs['username'])

django - prevent duplicates for users

Here is the Model class
class Album(models.Model):
name = models.CharField(max_length=256)
public = models.BooleanField(default=False)
user = models.ForeignKey(get_user_model())
class Meta:
unique_together = (("name", "user"),)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('photos:index')
Here is the View
class Create(CreateView):
model = Album
fields = ['name', 'public']
form_class = AlbumCreateForm
def form_valid(self, form):
form.instance.user = self.request.user
return super(Create, self).form_valid(form)
And here is the form Class
class AlbumCreateForm(ModelForm):
class Meta:
model = Album
fields = ['name', 'public']
labels = {'name': '', 'public': 'Public'}
def __init__(self,*args, **kwargs):
super(AlbumCreateForm, self).__init__(*args, **kwargs)
self.fields['name'].widget = forms.TextInput(
attrs={'placeholder': 'name'})
I can create album just fine, but what I would like to do is prevent duplicate albums from being created for a particular user. For example if user1 has already created album1, he should not be able to create another album named album1.
The place where I can do it is AlbumCreateForm. But AlbumCreateForm does not have any knowledge of current user. Any idea how it can be accomplished?
Pass user to form - add him to form kwargs by adding this method to view:
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(Create, self).get_form_kwargs(*args, **kwargs)
kwargs['user'] = self.request.user
return kwargs
Get user in form and check:
def __init__(self,*args, **kwargs):
self.user = kwargs.pop('user') # this line added
super(AlbumCreateForm, self).__init__(*args, **kwargs)
self.fields['name'].widget = forms.TextInput(
attrs={'placeholder': 'name'})
def clean(self):
if Album.objects.filter(user=self.user).exists():
raise forms.ValidationError('Error description')

How to set django many-to-many field to accept null

I am working on a python/django application. In my application there are 2 tables Store and Ad. That have many to many relation.
Class Store:
ads = models.ManyToManyField(Ad, null=True, blank=True)
Class Store:
ads = models.ManyToManyField(Ad)
I have tested it with both implementations given above but when i save my store without selecting an ad it gives me error:
ads: This field is required.
How can i set ads optional here???
View:
class StoreView(FormView):
form_class = StoreForm
success_url = "/"
template_name = 'store.html'
def __init__(self):
super(StoreView, self).__init__()
self.store = None
def get_form_kwargs(self):
kwargs = super(StoreView, self).get_form_kwargs()
kwargs['current_user'] = self.request.user
if 'store_id' in self.kwargs:
self.store = Store.objects.get(id=self.kwargs['store_id'])
kwargs['instance'] = self.store
kwargs['request'] = self.request
return kwargs
def get_context_data(self, **kwargs):
context = super(StoreView, self).get_context_data(**kwargs)
context['store_info'] = self.store
return context
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(StoreView, self).dispatch(*args, **kwargs)
def form_invalid(self, form):
return super(StoreView, self).form_invalid(form)
def form_valid(self, form):
self.object = form.save()
return super(StoreView, self).form_valid(form)
Form:
class StoreForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.fields['ads'] = forms.ModelMultipleChoiceField(
queryset=Ad.objects.filter(type=13),
widget=forms.CheckboxSelectMultiple,
label='Ads associated with this store'
)
def save(self, commit=False):
store = super(StoreForm, self).save(commit=True)
return store
class Meta:
model = Store
add required=False in definition ads field in the form. When you override a field in model form, no attributes are inherited from the model. You have to add all constraints to it like max_length, required etc.

Categories

Resources