I have this table.
class MyTable(BaseModel):
key = m.CharField(max_length=20,null=False,unique=True)
pre_json = m.JSONField(blank=True, null=True)
post_json = m.JSONField(blank=True, null=True)
And I use this model through ListView/UpdateView
list view is here.
class MyTableListView(LoginRequiredMixin, ListSearchView):
model = MyTable
form_class = MyTableForm
template_name = 'mytable_list.html'
class MyTableForm(forms.ModelForm):
key = forms.CharField(required=True)
pre_json = forms.JSONField
post_json = forms.JSONField
class Meta:
model = sm.ScenarioWorker
fields = ["key","key","pre_json","post_json"]
in list html template
{{obj.pre_json}}
in edit html template
{% render_field form.pre_json class="form-control" %}
Upper one shows None in template
Lower one shows null in textarea as placeholder.
Why this two are shown? or can I erase these?
I want to stop this.
Related
Say I have three models, a Professor model, a Course model, and a Review model. The user is allowed to make a Review, which reviews a Professor that teaches a certain Course.
I'm thinking of how to model the many to many relationship of Professor and Course, and how to reference that relationship in Review. My idea so far is to use models.ManyToMany to link Professor and Course.
Models.py (Prof)
class Prof(models.Model):
first_name = models.CharField(max_length = 20, unique = False)
last_name = models.CharField(max_length = 20, unique = False)
def __str__ (self):
return self.first_name + " " + self.last_name
class Course(models.Model):
name = models.CharField(max_length = 20, unique = True)
prof = models.ManyToManyField(Prof)
def __str__ (self):
return self.name
Models.py (Review)
class Review(models.Model):
message = models.TextField(max_length = 4000)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(null = True)
rating = models.IntegerField(
default = 5,
validators = [MaxValueValidator(5), MinValueValidator(0)]
)
prof = models.ForeignKey(Prof, related_name = 'reviews')
course = models.ForeignKey(Course, related_name = 'reviews')
user = models.ForeignKey(User, related_name = 'reviews')
def __str__ (self):
return self.message
forms.py
class ReviewForm(ModelForm):
rating = CharField(widget=TextInput(attrs={'type': 'number','value': 5, 'min': 0, 'max': 5}))
class Meta:
model = Review
fields = ['message', 'rating', 'prof', 'course', 'user']
This is my code so far for displaying the form
<h1>New Review</h1>
<form method="POST">
{% csrf_token %}
<p>{{ review_form.message }}</p>
<p>{{ review_form.rating }}</p>
<p>{{ review_form.prof }}</p>
<!-- The prof chosen's courses should be shown here -->
<button type="submit">Save</button>
</form>
Right now, forms.py shows all the objects under Course, and i'm not sure how to instead show the courses of a professor. Is it possible to filter the form after a prof is chosen from the drop down, to display the courses he/she teacher?
It sounds like you're going about this the right way. You haven't mentioned your urls.py structure yet, or views.py but the most straightforward way to do this is to display the courses by professor, taking the professor's id (or slug-field) in as a parameter - either in the URL (v straightforward) or as the output from a form on a previous page (and reload the template with a professor parameter) or in Ajax, depending on your appetite for shiny-new-things.
In your view, when you call the form, you can then do, along the lines from this answer -
form.courses.queryset = Course.objects.filter(professor__in=[professor.id,])
Note that I've put filtered on a list here, which only has one item - it does give you scope to expand, or to use a queryset for more complicated functions later.
Tweak as appropriate if you're using class-based views. :)
I have created a settings table in Django as per the below:-
class Settings(models.Model):
name = models.CharField(max_length=200)
class Meta:
verbose_name = "Settings"
verbose_name_plural = "Settings"
def __str__(self):
return self.name
class SettingChoices(models.Model):
setting = models.ForeignKey(Settings, on_delete=models.PROTECT)
choice = models.CharField(max_length=200)
class Meta:
verbose_name = "Setting Choices"
verbose_name_plural = "Setting Choices"
def __str__(self):
return '{0} - {1}'.format(self.setting, self.choice)
and a sample use of this would be:-
Setting = Circuit Type:
Choices:
DSL
4G
Fibre
then in another model I want to be able to reference this as set of choices
class Circuits(models.Model):
site_data = models.ForeignKey(SiteData, verbose_name="Site", on_delete=models.PROTECT)
order_no = models.CharField(max_length=200, verbose_name="Order No")
expected_install_date = models.DateField()
install_date = models.DateField(blank=True, null=True)
circuit_type = models.CharField(max_length=100, choices=*** here I would get model settings - Circuit Type - Choices ***)
currently I use a list in settings.py but its not fluid, I need my users to be able to alter these settings not for me to manually edit a list in settings.py and push changes each time
I attempted the below:
functions.py
def settings_circuit_types():
from home.models import SettingChoices
type_data = SettingChoices.objects.filter(setting__name='CIRCUIT_TYPES')
circuit_types = []
for c in type_data:
circuit_types.append(c.choice)
return circuit_types
models.py
from app.functions import settings_circuit_types
CIRCUIT_CHOICES = settings_circuit_types()
...
circuit_type = models.CharField(max_length=100, choices= CIRCUIT_CHOICES)
but this has thrown an error
dango.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
which is understandable, im wondering if what im trying to achieve is possible by other means?
Thanks
So this is a better way of doing this as i mentioned it in comment section:
1 - You don't need Settings and SettingChoices. They are basically the same so you can combine them into one model called Setting:
class Setting(models.Model):
name = models.CharField(max_length=200)
# if you need anything that you might think you need another model for,
# just think this way, add a BooleanField.
# for example if you have a setting available only for admins:
only_admin = models.BooleanField(default=False)
# then when you're going to make a from, just filter the options;
# options = setting.objects.filter(only_admin=False)
class Meta:
verbose_name = "Settings"
verbose_name_plural = "Settings"
def __str__(self):
return self.name
2 - And for Circuits model you just need a simple ForeignKey field:
class Circuits(models.Model):
site_data = models.ForeignKey(SiteData, verbose_name="Site", on_delete=models.PROTECT)
order_no = models.CharField(max_length=200, verbose_name="Order No")
expected_install_date = models.DateField()
install_date = models.DateField(blank=True, null=True)
circuit_type = models.ForeignKey(Setting, null=False, blank=False)
Now when you want to make a form for users to fill:
forms.py:
class CircuitsForm(forms.ModelForm):
class Meta:
model = Circuits
fields = ('install_date', 'circuit_type') # or other fields.
# and to filter which choices are available to choose from:
def __init__(self, *args, **kwargs):
super(CircuitsForm, self).__init__(*args, **kwargs)
self.fields["circuit_type"].queryset = setting.objects.filter(only_admin=False)
This way you have a safe and easy way to make forms for both users and your admins.
You can edit the admin panel itself or just make a url just for admin users with a form like this.
Also if you aren't that kind of people who uses django to render their form you can simply get the available choices in your view and pass it to the template like this:
settings = setting.objects.filter(only_admin=False)
and render it in a template like this:
<select name="circuit_type">
{% for setting in settings %}
<option value="{{ setting.pk }}">{{ setting.name }}</option>
{% endfor %}
</select>
Now you will have only choices you want them to show up in form and even if user tries to mess with template code and add more options, form won't allow them to be accepted and it will raise an error for it.
I have the following view
class AuthorList(FilterView):
model = Author
filterset_class = AuthorFilter
context_object_name = 'authors'
In the template, one of the field is {{ author.value }}, which is an integer.
What I would like to do is to show the sum of all {{ author.value }} in my template, but in a dynamic way (if some filters are used, the sum is updated with the current Queryset).
I have tried adding extra context with get_context_data but I couldn't find out how to make it in a dynamic way.
EDIT
tried this, still not working:
#property
def get_sum_values(self):
sum_values = self.objects.all().aggregate(Sum('value'))['value__sum']
return sum_values
and in the template: {{ authors.get_sum_values }}
I have also tried to add a print statement in the property, but nothing shows up, so I guess the function is not even loaded.
my models:
class Author(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
value = models.IntegerField(null=True, blank=True)
Have you tried doing the sum in the model as a function ?
#property
def wallet_amount_guests(self):
data_payments = self.user.earnings_set.filter(transaction_type='g').aggregate(Sum('amount'))['amount__sum']
if data_payments == None:
data_payments = 0
return data_payments
The above is just an example I have used before. You can then call in the html as blah.function_name
I have a situation where I would like to loop over all the tables available in database(stored in models.py) and print the meta attribute verbose_name only for tables having this attribute in the django html template. .This way the user can select the tables he want to view.
I have tried a few methods, but none seem to work..
This is my code :-
def tables_select(request):
if request.user.is_authenticated():
mdls = models.get_models(include_auto_created=False)
tables_list = [mdl._meta.verbose_name for mdl in mdls]
return render(request, 'cbm/tables_select.html', {'tables_list': tables_list})
else :
...
a check using hasattr() method doesn't work either :
for mdl in mdls:
if (hasattr(mdl._meta, 'verbose_name')):
tables_list.append(mdl._meta.verbose_name)
For the tables not having the verbose_name parameter, both of them return actual db table name.
UPDATE: These are the 2 model definitions in models.py :
This is the master table
class Ai(models.Model):
id = models.AutoField(db_column='ID', primary_key=True)
well = models.ForeignKey('Well', db_column='Well_ID')
samplename = models.CharField(db_column='sampleName', max_length=40, blank=True)
startdepth = models.FloatField(db_column='startDepth', blank=True, null=True)
... # Plus some other Columns
def __unicode__(self):
return self.samplename
class Meta:
managed = False
db_table = 'ai'
verbose_name = "Adsorbtion Isotherm"
AichIo is a dependent table on Ai
class Aich4Io(models.Model):
id = models.AutoField(db_column='ID', primary_key=True)
ai = models.ForeignKey(Ai, db_column='AI_ID')
pressurekpa = models.IntegerField(db_column='pressureKPa', blank=True, null=True)
pressureatm = models.FloatField(db_column='pressureAtm', blank=True, null=True)
meccreported = models.FloatField(db_column='meccReported', blank=True, null=True)
dafccreported = models.FloatField(db_column='dafccReported', blank=True, null=True)
class Meta:
managed = False
db_table = 'aich4io'
I don't want the names of dependent tables to be printed.
However for my html template:
{% for table in tables_list %}
{{ table }}<br>
{% endfor %}
The output is:
Adsorbtion Isotherm
aich4 io
After much research/combinations was able to find out this is generic behavior of django.
For models not having verbose_name parameter, the table/model name is returned as string.
To achieve my objective, I added verbose_name = 'DNS' for the models for which I didn't want to display the verbose_name. And in my code i did something like:
if mdl._meta.verbose_name == 'DNS':
# Do Nothing
else:
# My Logic.
You can check what type the verbose name is. If it's unicode then you can print the name
mdls = models.get_models(include_auto_created=False)
for mdl in mdls:
if isinstance(mdl._meta.verbose_name, unicode):
print mdl._meta.verbose_name
This is my model:
class Feature(models.Model):
name = models.CharField(max_length=75, blank=True)
order = models.SmallIntegerField()
group = models.ForeignKey(FeatureGroup)
def __unicode__(self):
return self.name
class Meta:
ordering = ['order']
The "Features" are being correctly display in the admin control panel based on the value specified in "order".
I have this in my view:
p = get_object_or_404(Phone.objects.prefetch_related('brand', 'features__feature', 'photo_set'), id=id)
I templates I have {% for feature in phone.features.all %}... {{ feature.feature }} ...
The values are being displayed correctly but in random order.
What's wrong and how can I overcome this problem?
Thanks.
How about the template filter dictsort
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#dictsort
{% for feature in phone.features.all|dictsort:"order" %}