I'm trying to log in a user and print all the latest 10 articles along with the number of comments and number of votes.
My views.py for that function goes like this:
article_query=Article.objects.filter(creator=user.id)
article = Article.objects.all()
latest_articles = article.order_by('-pub_date')
return render_to_response('home.html', {'article_user': article_query, 'user_info':user_info, 'latest_articles':latest_articles}, RequestContext(request))
However, I don't have a dedicated section as vote_count or comment_count stored in the database. I'm just storing the ids of the users that may have voted or commented separated by a semicolon (;)in a text field. Eg. votes--> (2;4;6;)
How can I output the number of votes in the template? Should I have to make a dedicated cell as votes_count in the database or should I achieve this by coding some cumbersome function in the views file and then displaying it? Which is the conventional method for websites having millions of users?
Related
I'm relatively new to Django development. I'm building a website where there is a section with tutorials. Lets say for my question a tutorial for Linked List. Since all the tutorials will be basically the same outline, it looks like that templates will do a good job here. What I want to achieve is that I can create new pages (tutorial entries ) in the admin panel, with text fields and so on (kind of like a blog without the relevance of the dates rather then the tutorials content). The challenge for me is, that there is a different amount of different types of data in one tutorial entries. For example one might have the structure:
text
code
text
image
text
code
and another one:
text
image
code
And if I made a new entry it should get generated with a template as it is done usually in Django. I thought about three ways to meet this dynamic behavior but I see difficulties in each and want to know what the best practice would be.
So the structure would be similar to a Blog:
class TutorialPost(models.Model):
title = models.CharField(max_length=200, unique=True)
text_content = models.TextField()
code_block = models.TextField()
#....
The problem here is that I don't know how to achieve thy dynamic behavior since I could need more text fields or code blocks in a different order.
I was also thinking of having only one text field and treating it as a markdown field. So I would get a markdown package such as Django MarkdownX, and would compile the contend of text_content. The problem here is, that I have much less freedom in how the design of the e.g. code block can look like (syntax highlighting, background and so on).
My last idea was that I again only have one text_content field as entry option but put plain text, code, images etc in own tags (similar to the three accents used here at stackoverflow) and process/parse these afterwards to present them in the proper order on request.
I'm looking forward to get some input.
I think you can do a model for each content type, like this.
class TextContent(models.Model):
body = models.TextField()
post = models.ForeignKey(TutorialPost, on_delete=models.CASCADE)
This way you can create multiple "content blocks" of the same time on a single post.
And for the order, you can create a custom OrderField, here is a example.
from django.core.exceptions import ObjectDoesNotExist
class OrderField(models.PositiveIntegerField):
def __init__(self, for_fields=None, *args, **kwargs):
self.for_fields = for_fields
super().__init__(*args, **kwargs)
def pre_save(self, model_instance, add):
if getattr(model_instance, self.attname) is None:
# No current value
try:
qs = self.model.objects.all()
if self.for_fields:
# Filter by objects with the same field values
# for the fields in 'for_fields'
query = {field: getattr(model_instance, field)\
for field in self.for_fields}
qs = qs.filter(**query)
# Get the order of the last item
last_item = qs.latest(self.attname)
value = last_item.order + 1
except ObjectDoesNotExist:
value = 0
setattr(model_instance, self.attname, value)
return value
else:
return super().pre_save(model_instance, add)
I am struggling to understand how to create a link in django's templates.
in my views.py file I have a list of lists (so a table). One of the fields may or may not contain links.
Views.py
#tableToView is a pd.DataFrame()
actualTable = []
for i in range(tableToView.shape[0]):
temp = tableToView.iloc[i]
actualTable.append(dict(temp))
#Returning the 'actualTable' list of lists to be printed in table format in the template
return render(response, "manual/manualinputs.html", {'defaultDates':defaultDates, 'prevFilterIn':prevFilterIn, 'actualTable':actualTable, 'DbFailure':DbFailure})
so imagine my actualtable has a field 'News' that may or may not contain a link, e.g.:
'hello there, go to https://www.google.com/'
How do I manage the fact that I want in my template to have the same string printed out, but with the address actually being a link?
I will also extend this to non-addresses (say twitter hashtags by parsing text).
Should I act on views or templates?
I did try to go the views way:
I substitute the
'hello there, go to https://www.google.com/'
with
'hello there, go to https://www.google.com/'
But I get the actual tags printed out, which is not what I want...
Any ideas?
If you change it on the view, you need to print it with |safe on the template.
So it would be
{{table.column|safe}}, this way your link will be a link and not a string
I'm currently working on a webpage using the django framework for python.
I need to have a page where admin user's can register an event into the system.
Event being: Location on a map, Description, Images, links etc..
I feel it's a bit less confusing If I have the user add location details on the first page but when he has finished choosing a location he could click next, this would take him to another page where he would finish filling out the information about the event.
I'm not sure but I think this is rather a database question than a django question.
How would I continue adding to the same table in a database between two seperate pages?
I thought about using timestamp so I could select the last modified table on the next page but I think that might be risky + if the user goes back to modify the table the timestamp is useless.
I'm using Django 1.5 + postgresql database. Any reading references that might be good to check out for this kind of operation?
I've done something similar to this before. I asked users to enter a zip code on one page and then based upon that zip code it loaded in different options for the form on the next page. Here is how I did it using request.session
Note that this is is my soultion to MY problem. This may not be exactly what you are looking for but might help you get a start. If anyone has a better solution I'd love to see it since I'm not entirely happy with my answer.
views.py
def find_zip(request):
c={}
form = FindZip()
c['form'] = form
if request.method == 'POST':
form = FindZip(request.POST)
c['form'] = form
if form.is_valid():
zip = form.data['zip']
form = ExternalDonateForm(initial={'zip':zip})
request.session['_old_post'] = request.POST
c['form'] = form
response = HttpResponseRedirect('/external')
return response
return render_to_response(
'find_zip.html',
c,
context_instance=RequestContext(request)
I then try to retrive that session from the previous view
def donate_external(request):
zip = None
if request.session.get('_old_post'):
old_post = request.session.get('_old_post')
zip = old_post['zip']
)
# rest of code ....
I'm having some problems in changing the empty label for a form. I've read the documentation https://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.ModelChoiceField and some pages here on stackoverflow, but I still don't get it. In my models, I have a tuple of countiescounty_choices = (('county1', _('county1')),('county2', _('county2')),('county3', _('county3')))
and the modelcounty = models.CharField(max_length=30, blank=True, default='n/a',choices=county_choices,verbose_name=_('county'), help_text=_('County')) I want to be able to override the 9 '-' empty label with a string in my own choice and to be able to translate it. So I imported everything from models and tried in forms county = forms.ModelChoiceField(queryset=Users.objects.all(),empty_label=_("my_own_choice")) and it does not work. I send it the {{ form.county }} variable in my html, but after my own choice, I get a wierd string 'sdadsada dsadadas' instead of my list of counties. Can you help me with that? Do I need to put the tuple with counties within a queryset? What if I don't want to send it a queryset at all?
Create a model for the counties and syncdb. This way you can manipulate and access them with a queryset, same way you do with Users. i.e. queryset=Counties.objects.all().
Look at the ModelChoiceField documentation for more help.
I'm trying to figure out if there's a way to do a somewhat-complex aggregation in Django using its ORM, or if I'm going to have to use extra() to stick in some raw SQL.
Here are my object models (stripped to show just the essentials):
class Submission(Models.model)
favorite_of = models.ManyToManyField(User, related_name="favorite_submissions")
class Response(Models.model)
submission = models.ForeignKey(Submission)
voted_up_by = models.ManyToManyField(User, related_name="voted_up_responses")
What I want to do is sum all the votes for a given submission: that is, all of the votes for any of its responses, and then also including the number of people who marked the submission as a favorite.
I have the first part working using the following code; this returns the total votes for all responses of each submission:
submission_list = Response.objects\
.values('submission')\
.annotate(votes=Count('voted_up_by'))\
.filter(votes__gt=0)\
.order_by('-votes')[:TOP_NUM]
(So after getting the vote total, I sort in descending order and return the top TOP_NUM submissions, to get a "best of" listing.)
That part works. Is there any way you can suggest to include the number of people who have favorited each submission in its votes? (I'd prefer to avoid extra() for portability, but I'm thinking it may be necessary, and I'm willing to use it.)
EDIT: I realized after reading the suggestions below that I should have been clearer in my description of the problem. The ideal solution would be one that allowed me to sort by total votes (the sum of voted_up_by and favorited) and then pick just the top few, all within the database. If that's not possible then I'm willing to load a few of the fields of each response and do the processing in Python; but since I'll be dealing with 100,000+ records, it'd be nice to avoid that overhead. (Also, to Adam and Dmitry: I'm sorry for the delay in responding!)
One possibility would be to re-arrange your current query slightly. What if you tried something like the following:
submission_list = Response.objects\
.annotate(votes=Count('voted_up_by'))\
.filter(votes__gt=0)\
.order_by('-votes')[:TOP_NUM]
submission_list.query.group_by = ['submission_id']
This will return a queryset of Response objects (objects with the same Submission will be lumped together). In order to access the related submission and/or the favorite_of list/count, you have two options:
num_votes = submission_list[0].votes
submission = submission_list[0].submission
num_favorite = submission.favorite_of.count()
or...
submissions = []
for response in submission_list:
submission = response.submission
submission.votes = response.votes
submissions.append(submission)
num_votes = submissions[0].votes
submission = submissions[0]
num_favorite = submission.favorite_of.count()
Basically the first option has the benefit of still being a queryset, but you have to be sure to access the submission object in order to get any info about the submission (since each object in the queryset is technically a Response). The second option has the benefit of being a list of the submissions with both the favorite_of list as well as the votes, but it is no longer a queryset (so be sure you don't need to alter the query anymore afterwards).
You can count favorites in another query like
favorite_list = Submission.objects.annotate(favorites=Count(favorite_of))
After that you add the values from two lists:
total_votes = {}
for item in submission_list:
total_votes[item.submission.id] = item.voted_by
for item in favorite_list:
has_votes = total_votes.get(item.id, 0)
total_votes[item.id] = has_votes + item.favorites
I am using ids in the dictionary because Submission objects will not be identical. If you need the Submissions themselves, you may use one more dictionary or store tuple (submission, votes) instead of just votes.
Added: this solution is better than the previous because you have only two DB requests.