I tried saving data on database using django views but it return a error.
def get_enroll(request, pk):
user = request.user
users = User.objects.filter(username=user)
course = Course.objects.filter(pk=pk)
chapter = ChapterModel.objects.filter(course = course)
abc = Enroll()
abc.save_enroll(users, course, chapter)
template_name = 'dashboard.html'
context = {'users':user,'course':course}
return render(request, template_name, context)
You can save it directly like:
Enroll(user=user, course=course, chapter=chapter).save()
You can simply use:
abc = Enroll.objects.create(users=users, course=course, chapter=chapter)
Since you havent provided your models, nor any logic of how you want this to work, I cannot give you a better solution than this one.
Hope this helps
Related
I apologize for my confusing title but I hope the code explains it better.
In my views.py file I have the follow view
def create_view(request):
context = {}
form = CreateForm(request.POST)
if request.method == "POST":
if form.is_valid():
instance = form.save(commit=False)
instance.author = request.user
instance.save()
instance.author.profile.participating_in = Post.objects.get(
title=instance.title
)
instance.save()
print(instance.author.profile.participating_in)
context["form"] = form
return render(request, "post/post_form.html", context)
when I print out the value of instance.author.profile.participating_in it shows up in my terminal however when I check the admin page it doesnt update at all. I'm sure I messed up somewhere silly but I cant seem to find it. Thanks!
participating_in is the profile model field, but you are not calling the save() method for profile anywhere.
You have to do it like the following:
profile = instance.author.profile
profile.participating_in = Post.objects.get(title=instance.title)
profile.save()
If participating_in is ManyToManyField then we can do it like this:
post = Post.objects.get(title=instance.title)
instance.author.profile.participating_in.add(post)
Note that add(), create(), remove(), clear(), and set() all
apply database changes immediately for all types of related fields. In
other words, there is no need to call save() on either end of the
relationship.
Look at Related objects reference
I am Building a BlogApp and I implement a feature to count the views of Post. BUT views are not showing in post page in Browser.
What i am trying to do
I am trying to count the number of views which post will got whenever the user visits.
The Problem
Post views are not showing in post page in browser.
What have i tried
1). I also tried models.IntegerField BUT that didn't worked for me , because whenever user refresh the page then it increase one view everytime for single user.
2). I followed some tutorials BUT the all of them were on Class Based Views and I am using Function Based Views.
3). Then i thought of IP address BUT that also didn't worked for me because it wasn't working for my server.
Then i think of a ManyToManyField in views variable. BUT it also not working for me, I don't know where is the problem.
views.py
def detail_view(request,pk):
data = get_object_or_404(BlogPost,pk=pk)
queryset = BlogPost.objects.order_by('viewers')
context = {'queryset':queryset,'data':data}
return render(request, 'mains/show_more.html', context )
models.py
class BloPost(models.Model):
post_owner = models.ForeignKey(User,default='',null=True,on_delete = models.CASCADE)
date_added = models
viewers = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='viewed_posts',editable=False)
show_more.html
1). This is showing auth.User.None
{{ data.viewers }}
2). This is showing all the posts.
{{ queryset }}
I don't what am i doing wrong.
Any help would be appreciated.
Thank You in Advance.
You should annotate your queryset, so:
from django.db.models import Count
def detail_view(request,pk):
queryset = BlogPost.objects.annotate(
num_views=Count('viewers')
).order_by('-num_views')
data = get_object_or_404(queryset, pk=pk)
context = {'queryset':queryset,'data':data}
return render(request, 'mains/show_more.html', context )
and then you can render this with:
{{ data.num_views }}
If you want to add the user to the viewers, you can run the logic to add the user to the viewers:
from django.db.models import Count
def detail_view(request,pk):
queryset = BlogPost.objects.annotate(
num_views=Count('viewers')
).order_by('-num_views')
data = get_object_or_404(queryset, pk=pk)
if self.user.is_authenticated:
__, created = Post.viewers.through.objects.get_or_create(
post=data,
user=self.request.user
)
if created:
data.num_views += 1
context = {'queryset':queryset,'data':data}
return render(request, 'mains/show_more.html', context )
That being said, this to some extent demonstrates that function-based views are often not well-suited for a view that requires to run logic that consists out of a number of separate parts. In that case it is better to work with mixins and define a class-based view in terms of these mixins.
Hi guys I'm building a simple django website where the user can look for long play. The problem right now is that I can't figure out why the filter, built with the django_filters library, doesn't work.
If you type "Queen" in the search bar in the home you are redirected to the searches.html where are listed all the LPs by Queen (just 4). On the left there's a filter. If you type "kind" in the form and submit then you should just see the album "Kind of Magic". This doesn't work. And I think the problem is the queryset "sp":
class searchesView(TemplateView):
template_name = "search/searches.html"
def post(self, request, *args, **kwargs):
print('FORM POSTED WITH {}'.format(request.POST['srh']))
srch = request.POST.get('srh')
if srch:
sp = Info.objects.filter(Q(band__icontains=srch)) | Info.objects.filter(Q(disco__icontains=srch))
myFilter = InfoFilter(request.GET, queryset=sp)
sp = myFilter.qs
paginator = Paginator(sp, 10)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(self.request, 'search/searches.html', {'sp':sp, 'myFilter':myFilter,
'page_obj': page_obj
})
else:
return render(self.request, 'search/searches.html')
I think the problem is the queryset because then I tried to build a result.html page where I listed all the LPs in the database and applied the same filter above and here it works perfectly:
def result(request):
result = Info.objects.all()
myFilter = InfoFilter(request.GET, queryset=result)
result = myFilter.qs
return render (request, 'search/result.html', {'result':result, 'myFilter':myFilter})
The difference is that in the first case I've got a TemplateView with a certain queryset, and in the second case I've got a simple function with a different queryset. Someone know what the problem could be? I uploaded to code on repl if you want to try out the website: https://Django-Template.edwardradical.repl.co
Thanks a lot!
Issue has to do with the mix of POST/GET here.
You are reading parameters out of both post/get dictionaries here, which is not a great pattern to go down.
In this case, a POST request to the url with the filters should yield the correct results ie:
POST /searches/?band=kind&disco=
{
srh: data
}
In current solution, I believe the srh is not included in the post body, which causes issue in queryset.
I tried to choose a good
I have several pages with one form each. I have had to create a view for each of these pages (about 20 different pages), but the code is almost similiar. I don't see any way to cut down on repeating code on this as the different views all have to deal with a different ModelForm instance.
Example could would be for one view:
def portfolio_dividend_new(request, profile_id):
profile = Profile.objects.get(id=profile_id)
post_req = False
if request.POST:
form = DividendForm(request.POST)
form.save()
post_req = True
form = DividendForm()
return render(request, 'plan/portfolio/new_dividend.html',
{'form': form,
'profile': profile,
'post_req': post_req}
)
Example of another view:
def portfolio_buyback_new(request, profile_id):
profile = Profile.objects.get(id=profile_id)
post_req = False
if request.POST:
form = SharebuybackForm(request.POST)
form.save()
post_req = True
form = SharebuybackForm()
return render(request, 'plan/portfolio/new_buyback.html',
{'form': form,
'profile': profile,
'post_req': post_req}
)
As you can see these views have much of the same code but since they have to instantiate different ModelForm instances I dont see how to keep them from becoming two views. This wouldnt be a problem if it only were two views but its becoming like 20 views which is not maintainable anymore.
How can I avoid violating the DRY principle when I have to work with different modelforms in each view ? I dont see CBV as any better solution here as the code itself isnt very long at all and its simple enough, but the problem is that much of the code repeats itself.
Any suggestions ?
Make the differences parameters and use functools.partial to partially apply them.
from functools import partial
def portfolio_page(model, the_url, request, profile_id):
profile = Profile.objects.get(id=profile_id)
post_req = False
if request.POST:
form = model(request.POST)
form.save()
post_req = True
form = model()
return render(request, the_url,
{'form': form,
'profile': profile,
'post_req': post_req}
)
portfolio_dividend_new = partial(
portfolio_page, DividendForm, 'plan/portfolio/new_dividend.html')
portfolio_buyback_new = partial(
portfolio_page, SharebuybackForm, 'plan/portfolio/new_buyback.html')
Or something like that. You only gave two examples. You could possibly pull out even more similarities, like the 'plan/portfolio/{}.html'.format(the_file) if they're all the same. Or it might take more parameters if they differ in more places.
You can even partial your partial if you use it a lot, like
page = partial(partial, portfolio_page)
portfolio_dividend_new = page(DividendForm, 'new_dividend')
portfolio_buyback_new = page(SharebuybackForm, 'new_buyback')
foopage = page(FooModel, 'foo')
barpage = page(BarModel, 'bar')
# etc.
I did not know you could use the "model" in that statement as a variable.
Classes are just another type of object in Python (as are functions), so you can assign them to variables and pass them as parameters to other functions, etc.
Context
I'm handling a form in a python view. Basic stuff.
def index(request):
# Handle form.
if request.method == 'POST':
form = CustomForm(request.POST)
if form.is_valid():
# Do stuff
return HttpResponseRedirect('/thankyou/')
else:
form = CustomForm()
# Render.
context = RequestContext(request, {
'form':form,
})
return render_to_response('app/index.html', context)
This form is shown on multiple pages, and I've ended up having duplicates of the form-handling code in multiple functions in views.py, rendering different templates. (However, the template code for the form resides in the base template)
That's dumb, so I tried looking around for ways to prevent the repeat of code. I like the suggested use of python decorators in this Stackoverflow question. I also found an excellent explanation of python's decorators here.
Question
I'm having trouble with trying to write the decorator. I need to return a form after the first if statement, followed by executing another if statement. But in a python function, no code after a return function gets executed... Does this require something like a nested decorator..?
Suggestions? Non-decorator suggestions welcome.
This is not the answer to your main question but this info may be helpful to you or somebody.
The question with suggestion about decorators is pretty old. Started from 1.3 version django have class based views - i think this is what you are looking for. By subclassing views you can reduce duplication of code (code from django docs just for example):
# Base view
class MyFormView(View):
form_class = MyForm
initial = {'key': 'value'}
template_name = 'form_template.html'
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
# <process form cleaned data>
return HttpResponseRedirect('/success/')
return render(request, self.template_name, {'form': form})
Now you can create another views classes based on MyFormView view. Form processing code stays same, but you can change it of course:
class AnotherView(MyFormView):
form_class = AnotherForm
initial = {'key1': 'value1'}
template_name = 'form1_template.html'
# you dont need to redefine post here if code stays same,
# post from base class will be used