forms.py
from django import forms
from .models import VendorApplication, VendorAppWorkFlow
import MySQLdb as mdb
from django.forms.fields import DateField, ChoiceField, MultipleChoiceField
from django.forms.widgets import RadioSelect, CheckboxSelectMultiple
from django.forms.extras.widgets import SelectDateWidget
con = mdb.connect('', '', '', '');
cursor1 = con.cursor()
cursor1.execute("select * from vendorapp_sharetable;")
columns = cursor1.description
num_fields = len(cursor1.description)
field_names = [i[0] for i in cursor1.description]
class CheckForm(forms.Form):
for index in range(num_fields):
field_names[index] = forms.BooleanField(required=False, label=field_names[index])
I want to add field_names values in forms.py to checkbox list without choices or how can I iterate them in choices to have checkboxMultiselect widget. As the count of field_names varies in my application am facing difficulty to add them to choices and use checkbox widget.
Something like:
field_names = [i[0] for i in cursor1.description]
choices = [(x, y) for (x, y) in enumerate (field_names)]
class CheckForm (forms.Form):
fields = forms.CheckboxMultiSelect (choices = choices, required = False)
Related
I have a declarative class that has an Enum column, and the Enum has a property that returns True/False based on the specific enumerated name or value. It would simplify life if I could do a query with a filter based on this property, such as the following (see implementation below):
session.query(MyTable).filter(MyTable.letter.is_vowel)
using something like the below straightforward attempt at an expression fails with
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with MyTable.letter has an attribute 'is_vowel'
The below implementation is too simple to allow for construction of the necessary query. Is there a way to do this? I thought maybe something in a Comparator might work, or maybe there's something more sophisticated that would do it?
import enum
from sqlalchemy import (
Column,
Enum,
Integer,
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
MyDeclarativeBase = declarative_base()
class Letter(enum.Enum):
A = 1
B = 2
C = 3
D = 4
E = 5
# and so on...
#property
def is_vowel(self):
return self.name in 'AEIOU'
class MyTable(MyDeclarativeBase):
__tablename__ = 'my_table'
id = Column(Integer, primary_key=True, autoincrement=True)
letter = Column(Enum(Letter), nullable=False)
#hybrid_property
def is_vowel(self):
"""Return True if the row's letter is a vowel."""
return self.letter.is_vowel
#is_vowel.expression
def is_vowel(cls):
return cls.letter.is_vowel
let's see if I can ask the questions correctly?
model.py
class Point(models.Model):
name = models.CharField(
"nome del sistema",
max_length=128,
)
x = models.FloatField(
"cordinata spaziale x",
)
y = models.FloatField(
"cordinata spaziale y",
)
z = models.FloatField(
"cordinata spaziale z",
)
distance = float(0)
def __str__(self) -> str:
return f"{self.name}"
#property
def get_distance(self):
return self.distance
#get_distance.setter
def get_distance(self, point):
"""
ritorna la distanza che ce tra due sistemi
"""
ad = float((point.x-self.x) if point.x > self.x else (self.x-point.x))
bc = float((point.y-self.y) if point.y > self.y else (self.y- point.y))
af = float((point.z-self.z) if point.z > self.z else (self.z-point.z))
return (pow(ad,2)+pow(bc,2)+pow(af,2))**(1/2)
class Meta:
verbose_name = "point"
verbose_name_plural = "points"
in the particular model there are two defs which calculate, save and return the distance with respect to the point we pass them
wenws.py
class PointViewset(viewsets.ModelViewSet):
"""
modelo generico per un systema
"""
queryset = Point.objects.all()
serializer_class = PointSerializers
filterset_class = PointFilter
in the wenws not that much particular to explain and base base the only thing we have to say and that as filters I use 'django_filters'
filters.py
import django_filters as filters
import Point
class CustomOrderFilter(filters.CharFilter):
def filter(self, qs:QuerySet, value):
if value in ([], (), {}, '', None):
return qs
try:
base = qs.get(name=value)
for point in qs:
point.get_distance = base
qs = sorted(qs, key= lambda x: x.get_distance)
except Point.DoesNotExist:
qs = qs.none()
return qs
class PointFilter(filters.rest_framework.FilterSet):
security = filters.ChoiceFilter(choices=security_choices
point= CustomCharFilter(
label = "point"
)
class Meta:
model = Point
fields = {
'name':['exact'],
}
now the complicated thing with 'CustomCharFilter' I pass in the http request the name of the system which then returns to me in the filter as value after I check that it is not empty and I start with returning the point that I have passed with base = qs.get ( name = value)
to then calculate and save the distance for each point with point.get_distance = base '' on the inside of the for, at the end I reorder the QuerySet with qs = sorted (qs, key = lambda x: x.get_distance) '' the problem that both with this way and with another that I have tried the QuerySet it 'transforms' into a list and this does not suit me since I have to return a QuerySet in the order of here I want. I don't know how to do otherwise, since order_by I can't use it since the distance is not inside the database
can someone help me?
So the problem is that you want to filter from a python function which cant be done in a query, as they only speak SQL.
The easy slow solution is to do the filtering in python, this might work if there are just a few Points.
points = list(Point.objects.all())
points.sort(cmp=comparison_function)
The actual real solution is to port that math to Djangos ORM and annotate your queryset with the distance to a given point, this is quite an advanced query, If you tell us your database server you use we can probably help you with that too.
ps. There is an abs() function in python to get absolute value instead of the if/else in get_distance
I am trying to use factory.faker to randomly choose from a list of four companies and use them as a traffic source for a list of generated names. I am using the below code:
from django.db import models
import factory
import factory.django
from datetime import datetime
from django.core.validators import MinValueValidator, MaxValueValidator
from faker import Faker
from faker.providers import BaseProvider
import random
fake = Faker()
class User(models.Model):
name = models.CharField(max_length=64)
address = models.CharField(max_length=128)
phone_number = models.CharField(max_length=32)
login_date = models.DateTimeField(default=datetime.now(), blank=True)
session_duration = models.IntegerField(default = 0, validators= [
MinValueValidator(0),
MaxValueValidator(5)
])
traffic_source = models.CharField(max_length=32)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
name = factory.Faker('name')
address = factory.Faker('address')
phone_number = factory.Faker('phone_number')
login_date = factory.Faker('date')
session_duration = factory.Faker('random_int')
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
The issue is that for all 200 iterations I perform using the following in the python shell:
for _ in range(200):
UserFactory.create()
I get the same company for every name, i.e. 'XYZ' for all 200 names.
Am I missing something? I want to get a different company for each of the 200 iterations. Any help is much appreciated. Thank you!
This comes from Python's parsing rules.
Why?
When you write this:
class UserFactory(factory.django.DjangoModelFactory):
...
traffic_source = random.choice(['XYZ', 'ABC', '123', '456'])
Python will execute the following steps:
Read the class declaration body;
Reach the line traffic_source = random.choice(['XYZ', 'ABC', '123', '456']);
Evaluate the call to random.choice, which might return 'ABC';
Once each line of the class body has been read (and its function calls evaluated), create the class:
UserFactory = type(
name='UserFactory',
bases=[factory.django.DjangoModelFactory],
{'traffic_source': 'ABC', ...},
)```
As you can see, the call to random.choice is performed only once, when parsing the class declaration.
This is, basically, the reason for all the factory.XXX declarations: they yield an object that will only execute its specific rules when building an instance from the factory.
So, what should you do?
Here, you should use:
Either factory.Faker using Faker's random_choices provider;
Or factory.fuzzy.FuzzyChoice:
class UserFactory(factory.django.DjangoModelFactory):
...
traffic_source = factory.Faker('random_choices', elements=['XYZ', 'ABC', '123', '456'])
alt_traffic_source = factory.fuzzy.FuzzyChoice(['XYZ', 'ABC', '123', '456'])
The main difference between factory.Faker('random_choices') and factory.fuzzy.FuzzyChoices is that factory.fuzzy.FuzzyChoices supports lazily evaluating generators; this is useful if you want to choose from a queryset:
factory.Faker('random_choices', elements=Company.objects.all()) will perform a DB query at import time;
factory.fuzzy.FuzzyChoice(Company.objects.all()) will only query the DB the first time UserFactory.create() is called.
While not truly random, the effect you're looking for when choosing from among a set of pre-existing records can also be achieved by using FactoryBoy's Iterator, which can also work with a QuerySet. For example, here I wanted every object to be created by someone different from the set of existing fake users:
from django.contrib.auth import get_user_model
...
# Then, within a factory class, for one of the fields:
created_by = factory.Iterator(get_user_model().objects.all())
I have created a Django form:
class AddFaceForm(forms.ModelForm):
class Meta:
model = Face
fields = ('person', 'x', 'y', 'w', 'h')
In the Face model, w is defined as
w = models.DecimalField(
'Relative width',
validators=[MinValueValidator(0.05), MaxValueValidator(1)]
)
If a user enters 0 for the width, the error message Django returns upon form validation is
Ensure this value is greater than or equal to 0.05.
So it nicely contains the value from the MinValueValidator. I would like to change it to "Relative width must be >= 0.05".
To achieve it, I tried customising errors in AddFaceForm Meta
class AddFaceForm(forms.ModelForm):
class Meta:
model = Face
fields = ('person', 'x', 'y', 'w', 'h')
error_messages = {
'w': {
'min_value': 'Relative width must be >= 0.05'
}
}
But this means hard-coding the 0.05 value. I would like to read it from the model definition. How can this be done?
Great question.
MinValueValidator is a subclass of BaseValidator. And, BaseValidator takes an optional message in its constructor. From the code you can see that the message can use the following three parameters: limit_value, show_value and value. limit_value is the minimum value for the validator which is 0.05 in this case. show_value is the cleaned value the user enters and value is the raw value they enter. Hence, you can do the following to achieve your goal:
from django.core.validators import MinValueValidator
from django.db import models
from django.utils.translation import ugettext_lazy as _
class Face(models.Model):
w = models.DecimalField(
'Relative width',
max_digits=5,
decimal_places=2,
validators=[MinValueValidator(0.05, _('Relative width must be >= %(limit_value)s'))],
)
Alternatively, if you'd rather specify the error message in a form then you can do the following:
from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import Face
class FaceForm(forms.ModelForm):
class Meta:
model = Face
fields = ['w']
error_messages = {
'w': {
'min_value': _('Relative width must be >= %(limit_value)s')
}
}
The DecimalField docs tell you that you can interpolate limit_value.
I'm trying to create a webapp in django 1.9 for task tracking and ordering. The different tasks are divided into spaces (like different projects). Now, I want to be able to choose what the task is assigned to in the CreateView.
The problem is, that I have a large number of users in my system, so I do not want to show a dropdown. Instead, I want to use a TextInput widget, to have the form check for the available options (this way I can also use typeahead on the client side).
This is the best I could come up with for the TaskCreate view:
class TaskCreate(LoginRequiredMixin, CreateView):
"""
a view for creating new tasks
"""
model = Task
fields = ['space', 'name', 'description', 'assigned_to', 'due_date']
template_name = "task_tracker/task_form.html"
success_url = reverse_lazy('tracker:my_open_task_list')
def get_context_data(self, **kwargs):
context = super(TaskCreate, self).get_context_data(**kwargs)
context['header_caption'] = 'Create'
context['submit_caption'] = 'Create'
context['all_usernames'] = [x.username for x in User.objects.all()]
return context
def get_form(self, form_class=None):
form = super(TaskCreate, self).get_form(form_class)
form.fields['assigned_to'].choices = [(x.username, x.id) for x in User.objects.all()]
form.fields['assigned_to'].initial = self.request.user.username,
form.fields['assigned_to'].widget = widgets.TextInput()
try:
form.fields['space'].initial = Space.objects.get(name=self.request.GET['space'])
finally:
return form
def form_valid(self, form):
form.instance.created_by = self.request.user
form.instance.assigned_to = User.objects.get(username=form.cleaned_data['assigned_to'])
return super(TaskCreate, self).form_valid(form)
But the thing is that this is not working - the form still considers my choice to be illegal, even when I type in a valid username.
I tried to switch places the x.username and x.id in the choice field but it didn't help me.
I'm stuck on this for a week now. Can anybody help me please?