I'm pretty new to Django and I'm unsure of whether I'm going in the right direction with this.
What I'm trying to do is, when the user is creating a Character in the Admin menu, if the user chooses faction Alliance, to bring up the Alliance_Races, and if not, the Horde_Races.
models.py
Factions = (
('Choose', 'Choose...'),
('Alliance','Alliance'),
('Horde', 'Horde'),
)
Alliance_Races = (
('Human','Human'),
('Dwarf', 'Dwarf'),
('Night Elf', 'Night Elf'),
('Gnome', 'Gnome'),
('Draenei', 'Draenei'),
('Worgen', 'Worgen'),
('Pandaren', 'Pandaren'),
)
Horde_Races = (
('Orc','Orc'),
('Undead', 'Undead'),
('Tauren', 'Tauren'),
('Troll', 'Troll'),
('Blood Elf', 'Blood Elf'),
('Goblin', 'Goblin'),
('Pandaren', 'Pandaren'),
)
class Character(models.Model):
character_name = models.CharField(max_length=100, default="")
faction = models.CharField(max_length=8, choices=Factions, default='none')
race = ""
def __str__(self):
return self.character_name
def race_options(self):
if self.allied_with == "Alliance":
self.race = models.CharField(max_length=8, choices=Alliance_Races, default='none')
elif self.allied_with == "Horde":
self.race = models.CharField(max_length=8, choices=Horde_Races, default='none')
I'd appreciate any help. Thanks in advance!
Try using model inheritance:
class Character(models.Model):
character_name = models.CharField(max_length=100, default="")
def __str__(self):
return self.character_name
class Meta:
abstract = True
class AllianceCharacter(Character)
race = models.CharField(choices=Alliance_Races)
class HordeCharacter(Character)
race = models.CharField(choices=Horde_Races)
Related
I've got a django view with a small amount of business logic in it. However it would be useful to use this information elsewhere so it feels like something that I could put into a model however I'm not entirely sure how to go about doing this. Mainly because I need specific user data. This is what I have so far:
views.py
def create_budget(self, context):
starting_point = BudgetStartingPoint.objects.filter(owner=self.request.user)
running_tally = starting_point[0].starting_amount
budget_dict = {}
for transaction in self.get_queryset():
if transaction.income_type == "IN":
running_tally += transaction.transaction_amount
else:
running_tally -= transaction.transaction_amount
budget_dict[transaction] = [running_tally, transaction.income_type]
context['budget'] = budget_dict
models.py
class BudgetTransaction(models.Model):
"""
Individual transaction for Budget
"""
transaction_types = [
('fixed', 'Fixed'),
('extra', 'Extra'),
]
income_types = [
("IN", "Income"),
("OUT", "Expense"),
]
frequencies = [
('weeks', 'Weekly'),
('fort', 'Fortnightly'),
('4week', 'Four Weeks'),
('months', 'Monthly'),
('years', 'Yearly'),
]
today = datetime.today().date()
id = HashidAutoField(
primary_key=True, salt=f"transaction{settings.HASHID_FIELD_SALT}"
)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
help_text="Owner of the item"
)
category = models.ForeignKey(BudgetCategory, on_delete=models.CASCADE, default=1, null=True)
transaction_type = models.CharField(max_length=40, choices=transaction_types, default=1)
transaction_name = models.CharField(max_length=100, null=False)
transaction_amount = models.FloatField(null=False, default=100)
income_type = models.CharField(max_length=20, choices=income_types, default="IN")
next_date = models.DateField(null=False, default=today)
frequency = models.CharField(max_length=20, choices=frequencies, default=1)
complete = models.BooleanField(default=False)
def __str__(self):
return self.transaction_name
class Meta:
ordering = ['next_date']
I feel like I have a lot of things that would be nice to have as a model method but they need to get the current user which I'm not sure how to do.
Not sure if this is what you mean but you can do:
def create_budget(self, context):
starting_point = BudgetStartingPoint.objects.filter(owner=self.request.user)
running_tally = starting_point[0].starting_amount
budget_dict = {}
for transaction in self.get_queryset():
running_tally = transaction.get_change(running_tally)
budget_dict[transaction] = [running_tally, transaction.income_type]
context['budget'] = budget_dict
class BudgetTransaction(models.Model):
....
def get_change(self,value):
return value + (
self.transaction_amount
if self.income_type == "IN" else
-self.transaction_amount
)
I'm working on a project where they have various job types that I've tackled with CHOICES, however, I want to add conditionals for WHEN job type 1 is chosen, SUBTYPES x-y become choices. I am having trouble with the syntax of how you would do that. I've included my pseudocode below... I appreciate any help!
from django.db import models
class User(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Job(models.Model):
name = models.CharField(max_length=255)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='jobs')
JOB_CHOICES = (
('carpentry', 'Carpentry'),
('cleaning', 'Cleaning'),
('electrician', 'Electrician'),
('handyman', 'Handyman'),
('hvac', 'HVAC'),
('painting', 'Painting'),
('pest', 'Pest'),
('plumbing', 'Plumbing'),
('roofing', 'Roofing'),
('property', 'Property'),
)
jobType = models.CharField(max_length=30, choices=JOB_CHOICES, default='handyman')
# If JobType = Carpentry:
# CARPENTRY_CHOICES = (
# ('trim', 'trim')
# ('sheetrock', 'Sheetrock')
# ('windows', 'Windows')
# ('doors', 'Doors')
# ('cabinets and shelving', 'Cabinets and Shelving')
# ('other', 'Other')
# )
# jobType = models.CharField(max_length=30, choices=CARPENTRY_CHOICES, default='other')
def __str__(self):
return self.name
Django Models
Django Serializer
/api editor
I would probably go with a job_type model, which has a name and a 'subtype' field.
class JobType(models.Model):
SubTypeChoices = (...)
name = models.CharField()
subtype = models.CharField(choices=SubTypeChoices, ...)
class Job(models.Model):
....
job_type = models.ForeignKey(JobType, ...)
....
This way you can associate your 'subtypes' with one job_type. And if for some reason you can have several job_types for a Job, use a ManyToMany field.
I was thinking about making a Hostel Allocation Web application. It has models, Student, Room, Hostel. What I want is to create a function that allocates students after each year. For that, I thought in the student view each student after completing his four years of stay can click on vacate hostel after completing his degree, and for others, I want to create something that allocates them,
Now there are certain constraints, there are Undergraduate students with degree period 4 years and each year has access to different types of rooms, First-year triple sharing, second and third-year double sharing and fourth-year single rooms. Also, a Hostel has Ph.D. students as well but their stay period is not defined.
So, what I was thinking is that First years should be allotted by uploading a CSV file and I have made that part, So the next part is to allot subsequent years based on their preferences, So how could I make something like this in Django that allows them to make it based on their preference, I was thinking each student would be given a unique token, and while filling for rooms one student can do for a room, and that token needs to be entered. Is this the right way or should I do something else. I am a newbie please suggest me a good way to do this.
models.py
class Student(models.Model):
name = models.CharField(max_length = 40,help_text = "Name of the student")
entry_number = models.CharField(max_length = 11,help_text = "Entry Number of a student")
hostel_name = models.ForeignKey('Hostel', on_delete = models.SET_NULL,null = True)
room = models.ForeignKey('Room',on_delete = models.SET_NULL,null = True)
CHOICES = (
('m','Male'),
('f','Female'),
('e','Engaged'),
)
gender = models.CharField(max_length=1,choices=CHOICES)
def __str__(self):
return '%s, %s' % (self.name,self.entry_number)
def get_absolute_url(self):
return reverse('student-detail',args=[str(self.id)])
class Meta:
verbose_name="Student Record"
class Hostel(models.Model):
name= models.CharField(max_length= 15)
locality= models.URLField(max_length= 200, blank= True, default='',help_text='Google maps URL of the hostel')
total_rooms= models.PositiveSmallIntegerField(null=True, blank =True)
CHOICES = (
('m', 'Male'),
('f', 'Female'),
('e', 'Engaged'),
)
gender = models.CharField(max_length=1, choices=CHOICES, verbose_name=_('Type of Hostel'), help_text='Either Boys/Girls or Married students Hostel')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('hostel-detail',args=[str(self.id)])
class Meta:
verbose_name="Hostel Record"
class Room(models.Model):
hostel= models.ForeignKey(Hostel, on_delete=models.CASCADE)
name= models.CharField(max_length = 5)
floor= models.CharField(max_length = 1, blank=True)
wing= models.CharField(max_length = 1, blank=True)
comment= models.CharField(max_length = 100,blank=True, default = "comment here")
room_capacity = models.PositiveSmallIntegerField(validators=[MaxValueValidator(3),])
room_accomodation= models.PositiveSmallIntegerField()
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('room-detail',args=[str(self.id)])
class Meta:
verbose_name="Room Record"
So, the problem might be a bit too specific, I am not sure but I think I missed something in the way I fill my class in the commandBase.
And what I have at the moment is :
In the back office, in the sources / articles list everything is right. But in my page, articles parsed fro the .csv are not displayed.
Here is the model :
class Article(ModelMeta, TranslatableModel):
taints_cache = True
"""
Press article element,
"""
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
date_realization = models.DateField(_('Realised in'),
default=timezone.now)
image = FilerImageField(verbose_name=_('Featured image'), blank=True,
null=True,
on_delete=models.SET_NULL,
related_name='image_press_article',
help_text=_('Set if the article will be featured'))
sources = models.ManyToManyField(ArticleSource, verbose_name=_('Source'),
blank=False, null=True, related_name='sources_press_article')
regions = models.ManyToManyField(Country, verbose_name=_('Country of the article'),
blank=True, null=True,
related_name='regions_press_article')
global_regions = models.BooleanField('Global', default=True)
featureArticle = models.BooleanField(_('Feature'), help_text=_('Feature this article'), default=False)
sites = models.ManyToManyField(Site, verbose_name=_('Sites'), blank=True,
null=True,
help_text=_('Select sites in which show the project.'))
article_url = models.CharField(_('Article Url'), max_length=310, blank=False,
help_text=_('Use to link to the original source'))
countries_displayed_in = models.ManyToManyField(
Country,
verbose_name=_('Countries displayed in'),
blank=True,
null=True,
related_name='displayed_in_press_article',
help_text='Select the countries in which this project will be visible.'
'If not selected, the project will be visible in all countries otherwise it will be'
'visible only for users that are located in the countries selected')
translations = TranslatedFields(
title=models.CharField(_('title'), max_length=510),
slug=models.SlugField(_('slug'), blank=False, db_index=True, max_length=300),
description=HTMLField(_('article description if featured'), default='', blank=True,
configuration='HTMLFIELD_CKEDITOR_SETTINGS_CONTENT'),
meta_description=models.TextField(verbose_name=_('article meta description'),
blank=True, default=''),
meta_keywords=models.TextField(verbose_name=_('article meta keywords'),
blank=True, default=''),
meta_title=models.CharField(verbose_name=_('article meta title'),
help_text=_('used in title tag and social sharing'),
max_length=255,
blank=True, default=''),
meta={'unique_together': (('language_code', 'slug'),)}
)
objects = ProjectManager()
_metadata = {
'title': 'get_title',
'description': 'get_description',
'keywords': 'get_keywords',
'locale': None,
'image': 'get_image_full_url',
'published_time': 'date_created ',
'modified_time': 'date_modified',
# Handle the get_absolute_url in the view to have access to the request
# and so, to the current_app namespace instance
# 'url': 'get_absolute_url',
}
def country(self):
return "\n".join(([p.name for p in self.regions.all()]))
def source(self):
return "\n".join([p.name for p in self.sources.all()])
def get_title(self):
title = self.safe_translation_getter('meta_title', any_language=True)
if not title:
title = self.safe_translation_getter('title', any_language=True)
return title.strip()
def get_keywords(self):
return self.safe_translation_getter('meta_keywords').strip().split(',')
def get_description(self):
description = self.safe_translation_getter('meta_description', any_language=True)
if not description:
description = self.safe_translation_getter('description', any_language=True)
return escape(strip_tags(description)).strip()
def get_image_full_url(self):
if self.image:
return self.image.url
return ''
class Meta:
verbose_name = _('Press article')
verbose_name_plural = _('Press articles')
get_latest_by = 'date_realization'
def __str__(self):
title = self.safe_translation_getter('title', any_language=True)
return title if title is not None else '(not translated)'
def save(self, *args, **kwargs):
if (self.article_url[:4] != "http") and (self.article_url[:5] != "https"):
self.article_url = "https://" + self.article_url
super(Article, self).save(*args, **kwargs)
main_lang = self.get_current_language()
for lang in self.get_available_languages():
self.set_current_language(lang)
if not self.slug and self.title:
self.slug = slugify(self.title)
self.set_current_language(main_lang)
self.save_translations()
def get_slug(self):
return self.safe_translation_getter(
'slug',
language_code=get_language(),
any_language=False)
And here is what I do in order to add my new articles, in the django command :
class Command(BaseCommand):
help = 'Import list of press article from .csv'
def handle(self, *args, **options):
ArticleFile = csv.reader(open(args[0]), delimiter=',')
global_article = ""
_country = ""
current_site = Site.objects.get_current()
for row in ArticleFile:
if row[0] != "Order":
if row[7] == "TRUE":
global_article = "True"
elif row[7] == "FALSE":
global_article = "False"
_source = ArticleSource.objects.create(name=row[5])
logging.info("\n\n URL: " + row[9] + "\n")
new_article = Article(
article_url=row[9],
global_regions=global_article,
title = row[8],
date_realization=datetime.strptime(row[4] + '-' + row[3] + '-' + row[2], '%Y-%m-%d').date(),
#sites=current_site,
)
new_article.save()
new_article.sources.add(_source)
new_article.sites.add(current_site)
logging.info("\n\n title: " + new_article.title)
if row[0] == "5":
break
When I check the DB and compare articles from the parsing and article added from the back-office, the only difference I noticed is the language.
For the ones added by hand it's :
"en" and for the ones from the .csv it's "en-us".
So it might be the problem but I am not sure.
And even if it is, I don't know how to "force it" to be 'en' instead of 'en-us'.
Does anyone has a clue about it ?
Am I doing it right ? It's the first time I parse a csv and populate and external model with python / django.
Many thanks.
Wow, so the language was the problem.
I found this :
from django.utils.translation import activate
I just had to add :
class Command(BaseCommand):
help = 'Import list of press article from .csv'
def handle(self, *args, **options):
activate('en')
To my code and now everything's displaying correctly !
By the way, I am still wondering if I am populated my class the right way.
Feel free to comment, I would love to learn !
So I have these models Question, Answer, and UserAnswer that make up a quiz. The problem I'm facing is making a form that validates with these models. I have an idea of how to do it but it's not working.
class QAForm(forms.Form):
answers = forms.ChoiceField(label='Question is this', choices=[('Answer1','Answer1'),('Answer2','Answer2')], widget=forms.RadioSelect())
This works for 1 form, not for thousands. How would I modify this code so that users sees all of the user-generated questions & answers as form and can provide their own answer to it.
I have this (it works but I know it's not a good practice):
def questions(request):
queryset = Questions.objects.all()
if request.method =='POST':
a = request.POST['answer']
answer = Answer.objects.get(answer=a)
importance = request.POST['importance']
q = request.POST['question']
question = Questions.objects.get(id=q)
try:
user_answer = UserAnswers.objects.get(owner=request.user, question=question)
user_answer.answer = answer
user_answer.importance = importance
user_answer.save()
except:
user_answer = UserAnswers(owner=request.user, question=question, answer=answer, importance=importance)
user_answer.save()
else:
try:
current = UserAnswers.objects.all().filter(owner=request.user)
except:
current = ''
return render_to_response("questions/base.html", locals(), context_instance=RequestContext(request))
My models:
class Answer(models.Model):
answer = models.CharField(max_length=120)
question = models.ForeignKey('Questions', null=True, blank=True)
def __unicode__(self):
return self.answer
IMPORTANCE = (
('Irrelevant', 'Irrelevant'),
('A Little Important', 'A Little Important'),
('Somewhat Important', 'Somewhat Important'),
('Very Important', 'Very Important'),
('Mandatory', 'Mandatory'),
)
class Questions(models.Model):
owner = models.ForeignKey(User)
question = models.CharField(max_length=300)
importance = models.CharField(max_length=120, choices=IMPORTANCE, null=True, blank=True)
updated = models.DateTimeField(auto_now=False, auto_now_add=True)
timestamp = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.question
class Meta:
verbose_name ='Question'
verbose_name_plural ='Questions'
class UserAnswers(models.Model):
owner = models.ForeignKey(User)
question = models.ForeignKey(Questions)
answer = models.ForeignKey(Answer)
importance = models.CharField(max_length=120, choices=IMPORTANCE)
def __unicode__(self):
return str(self.owner) + " " + str(self.answer) + " " + str(self.importance)
How about this? (Haven't actually tested it, but it should work)
class QuestionForm(forms.ModelForm):
answer = forms.ChoiceField(required=True, widget=forms.RadioSelect())
def __init__(self, question=None, *args, **kwargs):
super(QuestionForm, self).__init__(*args, **kwargs)
self.fields['answer'].choices = [(a.text, a.value) for a in Answer.objects.filter(question=question)]
class Meta:
model = Question
fields = ('text')
Then initiating it like -
q = Question.objects.get(pk=1)
qform = QuestionForm(instance=q)
This can be done when you want just one form. You can use a FormSet if you want thousands of it.
PS: I'm assuming the Answer model has a foreignkey to the Question model and they have already been filled up.
Latest code for your demand. You can try this code :
class QuestionForm(forms.ModelForm):
answer = forms.ChoiceField(required=True, widget=forms.RadioSelect())
def __init__(self, question=None, *args, **kwargs):
super(QuestionForm, self).__init__(*args, **kwargs)
self.fields['answer'].choices = [(a.text, a.value) for a in Answer.objects.filter(question=question)]
class Meta:
model = Question
fields = ('text')
general knowledge