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'])
Related
I have BaseContext and Listview which is for Searching in multiple models, Search Class inherits from BaseContext. I set the current user to context and want to use it in my def get_queryset method, But it doesn't work. I think in Search CBV get_context_data execute after get_queryset that's why, self.user is None.
class BaseContext(ContextMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
request = self.request
if request.COOKIES.get('token') is not None:
...
user = Users.objects.filter(user_id=user_id).first()
context.update({'current_user': user})
context.update({'is_logged_in ': True})
else:
context.update({'is_logged_in ': False})
return context
class Search(BaseContext, ListView):
template_name = 'search.html'
context_object_name = "results"
paginate_by = 15
user = None
def get_queryset(self):
query = self.request.GET.get('search', None)
if query is not None and self.user is not None:
...
return queryset_chain
return faqModel.objects.none()
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
if 'is_logged_in' in context and context['is_logged_in']:
self.user = context['current_user']
else:
redirect("index")
return context
My question is how can I get context data in def get_queryset(self)?
for Listview get_quersyset() is called before get_contex_data() , hence getting context data is not possible in get_queryset()
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
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
here is the views.py for registration redux. i am a little bit confused and i don't really understand how to pass in context variables.
class RegistrationView(BaseRegistrationView):
SEND_ACTIVATION_EMAIL = getattr(settings, 'SEND_ACTIVATION_EMAIL', True)
success_url = 'registration_complete'
def register(self, request, form):
if Site._meta.installed:
site = Site.objects.get_current()
else:
site = RequestSite(request)
if hasattr(form, 'save'):
new_user_instance = form.save()
else:
new_user_instance = UserModel().objects.create_user(**form.cleaned_data)
new_user = RegistrationProfile.objects.create_inactive_user(
new_user=new_user_instance,
site=site,
send_email=self.SEND_ACTIVATION_EMAIL,
request=request,
)
signals.user_registered.send(sender=self.__class__,
user=new_user,
request=request)
return new_user
BaseRegistrationView inherits from FormView, which has in its inheritance chain django.views.generic.base.ContextMixin. This defines the get_context_data method, which returns context as a dict. You can override that method and add in your own variables like so:
class RegistrationView(BaseRegistrationView):
...
def get_context_data(self, **kwargs):
context = super(RegistrationView, self).get_context_data(**kwargs)
context['key'] = value
return context
I have a FormView that is basically a product page. You can view product details and request the product from a form on that page. I want the page to be set up so that anyone can view the page, but only people that are logged in can request the product. To do this, I added a login_required decorator to the post function in the FormView, but I get the error:
'QueryDict' object has no attribute 'user'
How can I code this view/form so it acts as I described?
View:
class RedeemReward(SingleObjectMixin, FormView):
template_name = 'reward.html'
slug_field = 'reward_slug'
form_class = Redeem_Reward
model = Reward
#method_decorator(login_required)
def post(self, request, *args, **kwargs):
return super(RedeemReward, self).post(request, *args, **kwargs)
def form_valid(self, form):
form_class = self.get_form_class()
form = self.get_form(form_class)
#form = self.get_form(self.get_form_class())
#form.save(self.request.POST)
form.save(self.request.POST)
return super(RedeemReward, self).form_valid(form)
def get_success_url(self):
return reverse('reward_confirmation', args=(self.object.reward_slug, self.object.reward_code))
def dispatch(self, *args, **kwargs):
self.object = self.get_object()
return super(RedeemReward, self).dispatch(*args, **kwargs)
Form:
class Redeem_Reward(forms.Form):
quantity = forms.IntegerField(label=_('Quantity'), error_messages={'invalid':'Must be a valid number'})
reward_name = forms.CharField(max_length=50, widget=forms.HiddenInput(), label=_('Reward Name'), error_messages={'invalid':'Invalid reward'})
def clean_quantity(self):
"""
Validate that the user entered a valid number.
"""
return self.cleaned_data['quantity']
def clean_reward_name(self):
"""
Validate that this reward code exists.
"""
try:
existing_reward = Reward.objects.get(reward_name=self.cleaned_data['reward_name'])
except ObjectDoesNotExist:
raise forms.ValidationError(_("The reward you requested does not exist."))
return self.cleaned_data['reward_name']
def save(self, request, *args, **kwargs):
"""
Save all of the required data.
"""
user = request.user
#user_points = Points.objects.filter(affiliate__id=user.id).annotate(total_points=Sum('points'))
user_points = Affiliate.objects.filter(points__affiliate__id=user.id).annotate(total_points=Sum('points'))
user_points = user_points[0].total_points
error_message = {'lookuperror':'You need to provide a valid quantity',
'insufficient_points':"You don't have enough points for this purchase."}
try:
quantity = self.cleaned_data['quantity']
reward_name = self.cleaned_data['reward_name']
rewards = Reward.objects.get(reward_name=reward_name)
except LookupError:
raise Http404
try:
points_cost = -(rewards.reward_cost * quantity)
except ArithmeticError:
raise Http404
quote_price = -(points_cost)
if user_points >= quote_price:
reward_order = Points.objects.create(affiliate=user, reward=rewards, points=points_cost, from_reward=True, from_offer=False, from_referral=False)
status_cost = Status_Code.objects.create(short_name="Pending", name="The order is currently being reviewed", description="The order is in queue")
redeem_order = Redeem.objects.create(affiliate=user, reward=rewards, status_code=status_code)
redeem_details = Redeem_Details.objects.create(redeem=redeem_order, quantity=quantity, quote_price=quote_price)
return HttpResponseRedirect(reverse('reward_confirmation', args=(redeem_details.redeem_code,)))
else:
return render(request, 'reward.html', {'error_message':error_message['insufficient_points']})
You're passing self.request.POST to your form's save method, which is set to expect a request as its first argument. Or at least something that has a user attribute. If you pass in self.request instead, you will no longer get that particular error.
It is odd that you're reinstantiating form in your form_valid method, which receives the bound form as an argument.
You're returning HttpResponse objects from your form's custom save method, which is nonstandard. But as long as you're doing that, you should return them from your form_valid method.
In summary, something like this:
def form_valid(self, form):
return form.save(self.request)