Context:
I am creating a website to house some webcomics I made as a project to practice Django. I am adapting Django's tutorial to create the site (https://docs.djangoproject.com/en/2.0/intro/tutorial03/ About halfway down the page under "Write views that actually do something"). I am having some difficulty getting part of my view to work as expected.
Expectation:
What I see when I go to http://127.0.0.1:8000/futureFleet/ : latest_comic
What I want to see: A dictionary of my 2 comics.
Question:
I think I am doing something wrong at this line
context = {'latest_comic': latest_comic}. I am adapting this line from the tutorial. What do I do? What am I missing?
Models.py
class Comic(models.Model):
#title
comic_title_text = models.CharField(max_length=200)
#date
comic_pub_date = models.DateTimeField('comic date published')
#image
comic_location = models.CharField(max_length=200)
#explanation
comic_explanation_text = models.CharField(max_length=400, blank=True)
def __str__(self):
return self.comic_title_text
def was_published_recently(self):
return self.comic_pub_date >= timezone.now() - datetime.timedelta(days=1)
views.py
def index(request):
latest_comic = Comic.objects.order_by('-comic_pub_date')[:2]
context = {'latest_comic': latest_comic}
return HttpResponse(context)
# return render(request, 'futureFleet/index.html', context) This sends to the template but doesn’t work at the moment
Database
"Welcome Aboard" "2018-01-15 21:02:54" "/home/user/Desktop/django/djangoFutureFleet/mysite/futureFleet/static/futureFleet/images/1.JPG" "this is the first comic"
"Space Vaccine" "2018-01-15 23:02:22" "/home/user/Desktop/django/djangoFutureFleet/mysite/futureFleet/static/futureFleet/images/2.JPG" "This is comic 2"
The problem is with:
Comic.objects.order_by('-comic_pub_date')[:2]
You are asking Django for all Comic objects sorted by publication date. You then take the first two with [:2]. Here's a simple example of this syntax:
>>> a = [0,1,2,3,4]
>>> print(a[:2])
[0, 1]
What you're probably looking for is:
Comic.objects.order_by('-comic_pub_date').first()
That would only return the first result.
Have you connected the view to your urls.py? In order to access the view, you need to connect it to a URL. In your urls.py file, add
path('/',<your app name>.views.index),
or if you're using the old django:
url(r'', <your app name>.views.index),
After that, try this:
latest_comic = Comic.objects.all().order_by('-comic_pub_date')[:2]
You could try:
def index(request):
latest_comic = Comic.objects.order_by('-comic_pub_date')[:2]
dictionary = {'comic_1':latest_comic[0], 'comic_2':latest_comic[1]}
return HttpResponse(dictionary)
Note: latest_comic[0]
will return the first field value of the model, in your case: Welcome Aboard
If you want to access other fields you will need to do the following:
latest_comic[0].field_name
Related
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.
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
Im creating a music website. In this website, I would like to add the functionality of favorites so users could add songs to their favorite lists.
I have done everything but I don't know how to save it. Here is my code:
models.py
class Song(models.Model):
is_favorite = models.BooleanField(default=False)
def __str__(self):
return self.song_title
views.py
def song_detail(request,song_id):
song = Song.objects.get(pk=song_id)
favorite = song.is_favorite = True
return render(request, 'song_detail.html', {'favorite':favorite})
song_detail.html
<button onclick="{{favorite}}">Favourite</button>
While playing with the python shell, I found the problem:
Let s be the created song with pk=1,
d = Song.objects.get(pk=1)
d.is_favorite=True
d.save()
y = Song.objects.filter(is_favorite=True)
print(y)
->s
The problem was after making a song's is_favorite = True, we need to save it. But I don't know how to implement it in the code such that when a user clicks the button the boolean field changes to true. Thank you.
I solved it myself!
I changed the values of favorite from views to song.update(is_favorite=True).
I have searched around and see that most are pointing to a search that was created by Julien Phalip: http://julienphalip.com/post/2825034077/adding-search-to-a-django-site-in-a-snap
Also the answer seems to be here: Very simple user input in django
However I am very new to Django and wanted to create a view where I actually understand what is happening so I have been going through the official Django and the Tango with Rango tutorials but I do not see a straightforward example of what I am trying to understand in regards to a simple form search. The main question I have is why is POST used in the example instead of GET? I thought POST was used to "create" data entries in mysql whereas GET is used to lookup/search for data entries? Am I missing something fundamental about using one vs the other?
I have the following simple example from my app:
models.py
class hardware(models.Model):
text = models.CharField(max_length=200, unique=TRUE)
pub_date = models.DateTimeField(default=timezone.now)
def __unicode__(self):
return self.text
class Barcode(models.Model):
hardware = models.ForeignKey(Hardware)
text = models.CharField(max_length=50)
pub_date = models.DateTimeField(default=timezone.now)
def __unicode__(self):
return self.text
forms.py
class HardwareForm(forms.modelForm):
class Meta:
model = Hardware
fields = ['text'}
views.py
def hardware_search(request):
if request.method == 'POST':
search_id = request.POST.get('textfield', None)
try:
hardwarename = Hardware.objects.get(text = search_id)
html = ("<H1>%s</H1>", hardwarename)
return HttpResponse(html)
except Hardware.DoesNotExist:
return HttpResponse("no such hardware found")
else:
return render(request, 'search.html')
search.html
<form method="POST" action="/hardware_search.html">
{% csrf_token %}
<input type="text" name="textfield">
<button type="submit">Upload text</button>
</form>
My questions are is this the most simple way to request user input to search for and generate the search results? Why is POST used? I plugged in this code and it does seem to work but i just can't understand why.
Secondly how can I display asssociated foreignkey class along with the main class 'hardware' search results? Does the ForeignKey association give a shortcut way of displaying that data as well?
thanks!
The W3 has an excellent introduction to POST vs GET here. There is a lot to be said for why someone might use POST or GET, and what their roles should be. You are probably more interested in the differences from the user's (browser's) perspective. The biggest differences between using POST and GET in a browser, is that the GET request will display the parameters in the URL. Change your form to GET to see for yourself. The user will be taken to:
/hardware_search.html?textfield=Upload%20text
As opposed to where they are taken to when the form action is POST:
/hardware_search.html
The value of the textfield field is still sent to the server, but is not visible in the URL.
There are quite a few other differences in the behavior of GET and POST in form submission. I would highly recommend reading over that introduction by the W3.
You're right, POST is not really appropriate for a search form. Using GET here would be better.
The other thing wrong is that there's no need at all for a ModelForm, or really for any kind of Django form. You're not doing any validation, you're not even using the form for output, so it would be better to leave that out altogether. That makes the view look like this:
def hardware_search(request):
query = request.GET.get('textfield', None)
if query:
try:
hardwarename = Hardware.objects.get(text = query)
html = ("<H1>%s</H1>", hardwarename)
return HttpResponse(html)
except Hardware.DoesNotExist:
return HttpResponse("no such hardware found")
else:
return render(request, 'search.html')
and you can change the form action to GET.
I have been searching for a solution to what I thought would be a common request but have found very little while Googling. I am trying to create a 'cascading' set of dropdown menus, the normal sort of UI feature usually found in location forms where a user would select Country, City, Town etc.
The solution I have been trying to work with is https://github.com/digi604/django-smart-selects. However the documentation, what little there is of it, is quite confusing. Here are the models as I have them so far:
models.py
class InstrumentModelType(models.Model):
model_type = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.model_type)
class InstrumentManufactuer(models.Model):
manufacturer_model_type = models.ForeignKey(InstrumentModelType)
manufacturer = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.manufacturer)
class InstrumentEquipmentType(models.Model):
equipment_manufacturer = models.ForeignKey(InstrumentManufactuer)
equipment_type = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.equipment_type)
class InstrumentDetails(models.Model):
instrument_model_type = models.ForeignKey(InstrumentModelType)
instrument_manufacturer = ChainedForeignKey(InstrumentManufactuer,
chained_field='instrument_model_type',
chained_model_field='manufacturer_model_type',
auto_choose = True,
show_all = False)
instrument_equipment_type = ChainedForeignKey(InstrumentEquipmentType,
chained_field='instrument_manufacturer',
chained_model_field='equipment_manufacturer',
auto_choose = True,
show_all = False)
def __unicode__(self): # Python 3: def __str__(self):
return '%s %s %s' % (self.instrument_model_type, self.instrument_manufacturer, self.instrument_equipment_type)
When I choose an option from the first dropdown (instrument_model_type) neither of the other two dropdowns populate as expected. Ideally I want to be able to filter first by model type and then by manufacturer to show available equipment types. Can anyone see where I am going wrong?
I have included the reference in urls.py as described in the docs and have tried numerous combinations of field references (chained_field/chained_model_field) to ensure I have understood the relations correctly. I also noticed that simplejson referenced in widgets.py has been depreciated so I replaced this with json.
While trawling the posts here I found http://www.dajaxproject.com/forms/ but the author on the Github page recommends not to use the library.
Am I wrong in thinking this is a common request? Is there a Django solution baked in that I have missed? If it matters at all I am using Django 1.6.
Thanks in advance.
I just finished similar project and I guess your solution is:
class InstrumentEquipmentType(models.Model):
manufacturer_model_type = models.ForeignKey(InstrumentModelType)
instrument_manufacturer = ChainedForeignKey(InstrumentManufactuer,
chained_field='instrument_model_type',
chained_model_field='manufacturer_model_type',
auto_choose = True,
show_all = False)
equipment_type = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.equipment_type)
Let me know if it did not work to send you my example
Try Django Clever Selects
https://github.com/PragmaticMates/django-clever-selects
I use it in my Django 1.6 project. It is more usefull to operate chains in views and forms (in clever selects), not in models (like smart selects do).