How Can I add Choices in the Django User model - django-users

I want to add two choices to the Django User model and also I want to inherit a form from UserCreationForm that are derived from django.contrib.auth.forms.When I used the below code I got different error.Can anyone suggest a solution for this?
forms.py
TYPE_CHOICES =(
("individual", "Individual"),
("company", "Company"),
)
class UserForm(UserCreationForm):
first_name = forms.CharField(max_length=50)
type = forms.ChoiceField(choices=TYPE_CHOICES)
class Meta:
model = User
fields = ['first_name','type']
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
TYPE_CHOICES =(
("individual", "Individual"),
("company", "Company"),
)
class User(AbstractUser):
type = models.CharField(choices=TYPE_CHOICES,max_length=20)

You can use django model's choices for this. First create object for your choices.
your_choices = (
(1, u'Active'),
(2, u'Inactive')
)
Add these choices to your model class.
choice_field = models.IntegerField(choices=your_choices)
Now extend your form class.
class RegistrationForm(UserCreationForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
email = forms.EmailField(max_length=75)
choice_field = forms.ChoiceField(choices=your_choices)
class Meta:
model = User
fields = ("first_name", "last_name", "email", "choice_field",)

Related

Python Flask SQLalchemy sqlite3 prevent SQL injections in Database search

I would like to know how I should change my code to prevent it from Injections:
import sqlite3
def search_in_database(column,searched_data):
con = sqlite3.connect('db.sqlite3')
cursor = con.cursor()
cursor.execute(f"""SELECT
id
FROM
My_library
WHERE
{column} LIKE '%{searched_data}%'
;""")
all = [i for i in cursor.fetchall()]
return all
I found code in web which gives an example of how to do it:
from sqlalchemy.sql import text
# Create a connection conn
stmt = text("""SELECT * FROM users
WHERE user = :username AND password = :password""")
conn.execute(stmt, prams={"username": "foo", "password": "bar"})
but In my HTML file I would like to give to user possibility to choose the:
Place where he wants to search in Titles, authors, published_dates,isbn, language...
and when he choose where He what to search then he types the query.
How to do it in this case, avoiding Injections?
My data base:
class My_library(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(250))
authors = db.Column(db.String(100))
published_date = db.Column(db.Integer)
isbn_or_identifier = db.Column(db.String(15), unique=True)
page_count = db.Column(db.String(10000))
language = db.Column(db.String(3))
image_links = db.Column(db.String(500))
I also added validators:
from flask_wtf import FlaskForm
from wtforms import SubmitField,StringField
from wtforms.validators import ValidationError,DataRequired,Length, URL
from wtforms.fields.html5 import DateField,IntegerField,DateField,IntegerField, URLField
class AddRecValidators(FlaskForm):
title = StringField(label=('Title:'),validators=[DataRequired(), Length(min=1,max=50)])
authors = StringField(label=('Authors:'),validators=[Length(min=1,max=100)])
published_date = IntegerField(label=('Published date:'),validators=[Length(min=1,max=4)])
isbn_or_identifier = IntegerField(label=('ISBN:'),validators=[Length(min=1,max=15)])
page_count = IntegerField(label=('Page count:'),validators=[ Length(min=1,max=10000)])
language = StringField(label=('Language:'),validators=[ Length(min=1,max=3)])
image_links = URLField(label=('Image links:'))
submit = SubmitField(label=('Add to library'))
Thanks for help in advance :D
You can use sqlalchemy to build the query. For example:
q = My_library.__table__.select().where(
My_library.__table__.c.title == "The searched title"
)
but that's not exactly what you wanted. You can also address the columns by their names like this:
q = My_library.__table__.select().where(
My_library.__table__.c["title"] == "The searched title"
)
# or
q = My_library.__table__.select().where(
My_library.__table__.c["title"].like("%The searched title%")
)
Therefore you can do this:
q = My_library.__table__.select().where(
My_library.__table__.c[column].like(f"%{searched_data}%")
)
cursor.execute(q)
In case you only want the ID, you would do this:
q = sqlalchemy.select([My_library.__table__.c.id]).where(
My_library.__table__.c[column].like(f"%{searched_data}%")
)
# you can print(q) to see what it constructed
cursor.execute(q)
That was SQLAlchemy Query Language. You are using ORM. I suggest you read-up something about a session in flask first.
It is still possible to get to the column-name related attribute and I am not sure this is the most efficient way:
q = session.query(My_library.id).filter(
getattr(My_library, column).like(f"%{searched_data}%"),
)

How to define Auto evaluation and attempted multiple times constraint in MCQ for django model?

I am working on a MCQ based django project and based on my research I have below models that I got from 3rd party reference. Of course I had to make some modification based on my custom need. below is the snippet from models.py:
from django.db import models
from django.contrib.auth.models import User
from django.template.defaultfilters import slugify
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
class Quiz(models.Model):
name = models.CharField(max_length=1000)
questions_count = models.IntegerField(default=0)
description = models.CharField(max_length=70)
created = models.DateTimeField(auto_now_add=True,null=True,blank=True)
slug = models.SlugField()
roll_out = models.BooleanField(default=False)
class Meta:
ordering = ['created', ]
verbose_name_plural = 'Quizzes'
def __str__(self):
return self.name
class Question(models.Model):
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
label = models.CharField(max_length=1000)
order = models.IntegerField(default=0)
marks = models.IntegerField(default=0)
optional = models.BooleanField(default=False)
def __str__(self):
return self.label
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
text = models.CharField(max_length=1000)
is_correct = models.BooleanField(default=False)
def __str__(self):
return self.text
class QuizTakers(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
correct_answers = models.IntegerField(default=0)
completed = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
class Response(models.Model):
quiztaker = models.ForeignKey(QuizTakers, on_delete=models.CASCADE)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.ForeignKey(Answer,on_delete=models.CASCADE,null=True,blank=True)
def __str__(self):
return self.question.label
#receiver(post_save, sender=Quiz)
def set_default_quiz(sender, instance, created, **kwargs):
quiz = Quiz.objects.filter(id=instance.id)
quiz.update(questions_count=instance.question_set.filter(quiz=instance.pk).count())
#receiver(post_save, sender=Question)
def set_default(sender, instance, created, **kwargs):
quiz = Quiz.objects.filter(id=instance.quiz.id)
quiz.update(questions_count=instance.quiz.question_set.filter(quiz=instance.quiz.pk).count())
#receiver(pre_save, sender=Quiz)
def slugify_title(sender, instance, *args, **kwargs):
instance.slug = slugify(instance.name)
However, there are couple of points that I have implement for my MCQs for which I am not able to find proper solution. Below are the points.
1) Every quiz can be attempted multiple times by the quiz taker. No restriction.
2) Since the questions are in MCQ format, the quiz taker answers are auto-evaluated by the application.
Any help would be highly appreciated.
Thank you.
To answer both your questions:
Since every quiz can be done multiple times you will simply have a reset button. Once that button is clicked, it will delete the QuizTaker. You will then be able to create it again.
When you create a quiz all the questions have answers and one of those answers is correct. Therefore, you can define a function that checks if the response provided is equal to the correct answer then increment the number of correct answers by 1 for each correct answer.
I hope this helps!!

How can I add a CSS Class to a Flask-Table Column

I want to add CSS Classes to specific Columns, the Table is made via Flask-Table. But I only found how to add Classes to the whole table is there a way to add classes to a Column too?
class Table(Table):
classes = ["table", "table-hover", "clickable-row", "sortable"]
username = Col("Username")
vorname = Col("Vorname")
nachname = Col("Nachname")
gebdat = DatetimeCol("Gebdat", datetime_format="dd.MM.yyyy")
admin = BoolCol("Rolle", yes_display='Admin', no_display='Benutzer')
aktiv = BoolCol("Status", yes_display='aktiviert',
no_display='deaktiviert')
edit = LinkCol("Bearbeiten", 'benutzerverwaltung.benutzerBearbeiten',
url_kwargs=dict(id='id'))
You can pass a dict in the column_html_attrs keyword argument when declaring a specific column inside the table class:
class MyTable(Table):
col = Col('Label', column_html_attrs = {'class': 'my-class'})
For more details check this example from the Flask-Table github.

Django CMS - Copy relations in custom plugin not working

I have a problem with copy_relations after publishing a page.
I have a plugin with additional model. This model has ForeignKey to my plugin.
class InfContactForm(CMSPlugin):
name = models.CharField(max_length=50)
def copy_relations(self, oldinstance):
self.inf_contact_form.all().delete()
for inf_contact_form in oldinstance.inf_contact_form.all():
inf_contact_form.pk = None
inf_contact_form.plugin = self
inf_contact_form.save()
class InfContactFormAgreement(models.Model):
inf_contact_form = models.ForeignKey(InfContactForm, related_name="inf_contact_form")
agreement = HTMLField(blank=True, null=True)
The "InfContactFormAgreement" model is then used as stacked inline in "InfContactForm" plugin form.
Like it is written in docs, there is also copy_relations() method but when the page is published, nothing happens. When I get back again to edit mode InfContactFormAgreement is doubled every time I do it.
Here is also my cms_plugins.py file:
class PluginInfContactForm(CMSPluginBase):
render_template = '_contact_form.html'
name = name1
model = InfContactForm
require_parent = False
inlines = [AgreementStackedInline, ]
def render(self, context, instance, placeholder):
context['instance'] = instance
context = super(PluginInfContactForm, self).render(context, instance, placeholder)
agreements = instance.inf_contact_form.all()
context.update({
'agreements': agreements,
})
return context
plugin_pool.register_plugin(PluginInfContactForm)
Thank you for any advice.
instead of:
inf_contact_form.plugin = self
you should use:
inf_contact_form.inf_contact_form = self
and the resulting code should look like this:
def copy_relations(self, oldinstance):
self.inf_contact_form.all().delete()
for inf_contact_form in oldinstance.inf_contact_form.all():
inf_contact_form.pk = None
inf_contact_form.inf_contact_form = self
inf_contact_form.save()
regards
I had a similar situation, the only difference being that my many-to-many relationship was not in a plugin, but an extension (PageExtension).
In my case, #Dariusz solution did not work, and I had to update the implicit "inbetween" model that exists between the Extension model and the Associated model.
My solution (the key being the "through"):
class Extension(PageExtension):
tags_regions = models.ManyToManyField(Region, related_name="articles", blank=True)
def copy_relations(self, oldinstance):
for region_tag in oldinstance.tags_regions.through.objects.filter(extension=oldinstance):
region_tag.extension = self
region_tag.save()

Dynamic change element class in template based on model choices

I want to dynamically change an element class inside the template based on my model.
Here is my model:
class StockFlow(models.Model):
TYPE_CHOICES = (
(None, _('- Selecione -')),
('Entrada', (
(1, _('Pedido')),
(2, _('Pegou emprestado')),
(3, _('Entrada simples')),
)
),
('Saida', (
(4, _('Venda')),
(5, _('Emprestado')),
(6, _('Saida simples')),
(7, _('Avaria ou perda')),
(8, _('Presente')),
)
),
)
stock = models.ForeignKey('Stock')
value = models.IntegerField(null=True)
quantity = models.IntegerField(null=True)
date = models.DateField()
type = models.IntegerField(max_length=1, choices=TYPE_CHOICES, default=-1)
description = models.TextField(null=True)
I want to change the class based in if is "Entrada" or "Saida". How can I make this conditional statement to set my css class?
You should probably use a combination of Django forms and template context to accomplish this functionality...
Create a ModelForm from class StockFlow.
from django.forms import ModelForm
class StockFlowForm(ModelForm):
class Meta:
model = StockFlow
def __init__(self, *args, **kwargs):
super(StockFlowForm, self).__init__(*args, **kwargs)
self.fields['type'].widget.attrs['class'] = 'Entrada' if self.instance.type in [1,2,3] else 'Saida'
Now when you render this ModelForm in a template, the type field will have a dynamic class set to either 'Entrada' or 'Saida' depending upon the value of type.

Resources