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).
Related
I am trying to get the summary method the return the first 50 characters from the body.
class Blog(models.Model):
# Title for the Blog
title = models.CharField(max_length=255)
# Blog body
body = models.TextField()
def __str__(self):
return self.title
def summary(self):
return self.body[:50] # I get the error here
Your linter is getting confused since it expects self.body to be an instance of models.TextField, which does not support subscripting. However, Django's ORM will in reality substitute self.body with a string, which does support subscripting. Django does a fair amount of magic with metaclassess to provide this interface, and unfortunately linters usually aren't smart enough to detect this.
I want to check if the id of a page of exercises is inside of an array for solvedExercises. I thought this might be easy to do with a contained_by, but it doesn't work.
I've tried this line (but I also want to randomise the questions)
randomQuestions = Exercises.objects.filter(id__contained_by=(req.user.profile.exercitiiProvocari).order_by("?")
but it doesn't work.
I'm getting this error:
Unsupported lookup 'contained_by' for AutoField or join on the field not permitted, perhaps you meant contains or icontains?
I suppose this error comes from the fact that ID is an auto-generated field by django, but I have no idea how to fix it.
views.py
from django.shortcuts import render
from exercitii.models import Exercises
# Create your views here.
def index(req):
return render(req, "../templates/pagini/provocari.html")
def provocari(req):
randomQuestions = Exercises.objects.filter(id__contained_by=(req.user.profile.exercitiiProvocari).order_by("?")
print(randomQuestions)
return render(req, "../templates/pagini/provocare.html")
Exercitii model
from django.db import models
from django.contrib.postgres.fields import ArrayField
from lectii.models import Lectie
# Create your models here.
class Exercises(models.Model):
idLectie = models.ForeignKey(Lectie, on_delete=models.DO_NOTHING, blank=True, null=True)
intrebare = models.CharField(max_length = 300)
variante = ArrayField(models.CharField(max_length=300), null=True)
variantaCorecta = models.CharField(max_length = 1)
def __str__(self):
return self.intrebare
So what I'm actually doing is to try to make the difference of an array of all exercises with one with the IDs of already solved exercises, and randomising the result.
But when I'm trying to make this difference, I get that error.
Wouldn't a simple in lookup be sufficient for this case?
Assuming req.user.profile.exercitiiProvocari is some kind of array/list/container, you could try something like this:
randomQuestions = Exercises.objects.filter(id__in=req.user.profile.exercitiiProvocari)\
.order_by("?")
To exclude the seem questions, you could try using exclude(). This will return all questions that are NOT in req.user.profile.exercitiiProvocari and they should be in a random order:
randomQuestions = Exercises.objects.exclude(id__in=req.user.profile.exercitiiProvocari)\
.order_by("?")
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
Basic way to do it in the models.py, an example:
class Foo(models.Model):
title = models.CharField(max_length=200)
...
def custom_tag(self):
return ('custom: %s' % self.title)
custom_tag.allow_tags = True
custom_tag.short_description = _("Custom Tag")
or, if inside file of admin.py;
class FooAdmin(admin.ModelAdmin):
list_display = ['title', 'custom_tag', ...]
...
def custom_tag(self, instance):
return ('custom: %s' % instance.title)
custom_tag.allow_tags = True
custom_tag.short_description = _("Custom Tag")
admin.site.register(Foo, FooAdmin)
My question is, how does allow_tags and short_description works? and where I can find the relevant documentation?
I can't found it at the documentation or also at source code
You're looking at the development version of the documentation. If you look at the one for Django 1.10 (scroll down to "Deprecated since version 1.9") you'll see that they're removing the allow_tags option and replacing it with other ways of achieving the same thing. There are plenty of examples on how to use short_description though since it's not deprecated.
If you really want to see the source code, here's the line where it gets the short description. Don't worry about the allow_tags since it's removed in 1.11 - it should now done automatically by marking string as safe using mark_safe().
As a side note, you don't need to add the custom_tag() method in both places. The admin looks in both the model and the admin class for it so one is sufficient. If it's not going to be used outside the admin, I would recommend placing it inside the admin class and avoid making the model more complex.
I'm using the following combination of packages to work with mongodb in Django.
django-mongonaut==0.2.21
mongoengine==0.8.7
pymongo==2.7.2
I'm trying to set up my admin panel using mongonaut.
These are my two simple mongo engine models:
class Question(Document):
text = StringField(max_length=200)
def __str__(self):
return self.text
class QuestionList(Document):
title = StringField(max_length=200)
questions = EmbeddedDocumentField('Question') #This is the problem
def __str__(self):
return self.title
Currently I'm not using a ListField yet. When I try to add a new QuestionList using Mongonaut the following error pops up:
KeyError at /mongonaut/api/QuestionList/add/
u'Mongonaut does not work with models which have fields beginning with id_'
The mongonaut docs state that it allows working with EmbeddedDocumentFields. Still I get this error. What am I doing wrong?
Regards,
Swen