I'm working with Django 1.7.2 with generic relation (reason: project has two databases), and after import I don't want to have overwritten database.
I want to show only active season
Here is my model, is overwritten after import:
class Season(models.Model):
name = models.CharField('Name', max_length=255)
start = models.DateField('Start')
end = models.DateField('End')
def __unicode__(self):
return self.name
In another place in models.py file I create Generic relation to another model (SaleAndCycle) in another database:
def extend_models(sender, **kwargs):
if sender._meta.app_label != 'extend':
return
def set_stati(self, database='extend', save=True):
online_before = self.online
self.online = True
for flag in self.flags:
if flag.flag == 'offline':
self.online = False
if save and self.online != online_before:
self.save(using=database)
for name, name_singular, name_plural in (
('Season', 'Season', 'Seasons'):
if sender.__name__ == name:
sender._meta.verbose_name = name_singular
sender._meta.verbose_name_plural = name_plural
if sender.__name__ == 'Season':
sender.add_to_class('sale_and_cycles', generic.GenericRelation(SaleAndCycle))
sender.add_to_class('is_sale_active', property(
lambda o: o.sale_and_cycles.using('default')))
sender.add_to_class('is_cyclic_event_active', property(
lambda o: o.sale_and_cycles.using('default')))
sender.add_to_class('cycle_link', property(
lambda o: o.sale_and_cycles.using('default')))
I want to show all active Seasons for not login user:
def get_queryset(self):
seasons = Season.objects.all()
if not self.request.user.is_superuser:
all_seasons = Season.objects.filter(events_isactiveflags__is_active=True)
print all_seasons
I get error:
no such table: events_isactiveflag
But this table exists in my database.
by the line of code
Season.objects.filter(events_isactiveflags__is_active=True)
here events_isactiveflags__is_active=True means events_isactiveflags is a table and is_active is a column of the table. So no such table found named events_isactiveflags . if you are trying to get active sessions you can try this code
Session.objects.filter(expire_date__gte=timezone.now())
delete db and once again run syncdb
Related
I tried to create a table using a class that is not related to my database in django and this class is stored in models.py as shown below (InfoServer is the class). What I wanted to do is to use this class to populate my table using django_tables2. Add models.Model as a parameter is not an option because I don't want to save this class in the database.
Whenever I define the model = InfoServer in tables.py I got this error and I suppose it's because InfoServer did not take models.Model as a parameter.
TypeError: descriptor 'repr' of 'object' object needs an argument
Any help is appreciated.
models.py
class TestServeur(models.Model):
nom = models.CharField(max_length=200)
pid = models.CharField(max_length=200)
memoire = models.IntegerField(null=True)
class InfoServer:
# "This is a class to test my knowledge of python"
def __init__(self,p = '',c = 0,m = 0):
self.pid = p
self.cpu = c
self.memoire = m
def getData(self):
return ("A server with %s memory and %s cpu" % (self.cpu,self.memoire))
views.py
def index(request):
return HttpResponse("Hello, world. You're at the index.")
def cpu_view(request):
liste = []
proc1 = Popen(['ps','-eo','pid,%cpu,%mem,comm'], stdout=PIPE, stderr=PIPE)
proc2 = Popen(['grep','java'], stdin=proc1.stdout, stdout=PIPE)
proc1.stdout.close()
for line in iter(proc2.stdout.readlines()):
clean_line = line.decode("utf-8")
info_utiles = clean_line.split()
pid,cpu,mem,*rest = info_utiles
i1 = InfoServer(pid,cpu,mem)
liste.append(i1)
table = TestServeur(liste)
RequestConfig(request).configure(table)
return render(request, 'server/cpu.html', {'output': table})
tables.py
class TableServeur(tables.Table):
class Meta:
# model = InfoServer
fields = ['pid', 'memory', 'cpu']
template_name = 'django_tables2/bootstrap4.html'
As I can see, InfoServer class is not a Django Model. Also I don't think you need to use that directly anyway. So, you can simply provide a list with dictionary, and render it in template with table.
First, we need to update Table class and remove Meta class from it, as we are not going to use any django models.
class TableServeur(tables.Table):
pid = tables.Column()
memory = tables.Column()
cpu = tables.Column()
Now, adding a new object method to return dictionary from InfoServer class:
class InfoServer:
# "This is a class to test my knowledge of python"
def __init__(self,p = '',c = 0,m = 0):
self.pid = p
self.cpu = c
self.memoire = m
def getData(self):
return ("A server with %s memory and %s cpu" % (self.cpu,self.memoire))
def get_dict_data(self):
return {'pid': self.pid, 'cpu': self.cpu, 'memory': self.memoire}
Finally, update the view:
for line in iter(proc2.stdout.readlines()):
clean_line = line.decode("utf-8")
info_utiles = clean_line.split()
pid,cpu,mem,*rest = info_utiles
i1 = InfoServer(pid,cpu,mem)
liste.append(i1.get_dict_data())
table = TestServeur(liste)
return render(request, 'server/cpu.html', {'output': table})
More info can be found in documentation on how you can populate table with data.
Please refer to the code below
Transaction models
class Transaction(models.Model)
current_product_code = models.CharField(....)
previous_product_code = models.CharField(....)
#property
def status(self):
c_price = Product.objects.get(code=self.current_product_code).price
p_price = Product.objects.get(code=self.previous_product_code).price
if c_price == p_price:
return "Due"
elif c_price > p_price:
return "Upgrade"
else:
return "Downgrade"
Product model
class Product(models.Model):
code = models.CharField(....)
price = models.DecimalField(....)
My question: How can i obtain/filter transactions with upgrade/downgrade/due status. I am trying to create a custom admin filter which filter transaction based on their status but i fail what to put inside .filter() , check the method below
def queryset(self, request, queryset):
value = self.value()
if value == 'Upgrade':
return queryset.filter(***** HERE *****)
elif value == 'Downgrade':
return queryset.filter(***** HERE *****)
elif value == 'Unknown':
return queryset.filter(***** HERE *****)
return queryset
You really should use ForeignKey between Product and Transaction (for both: current_product_code and previous_product_code). This will allow you to use those relations in your querysets with ease.
My proposed models structure looks like this:
class Product(models.Model):
code = models.CharField(....)
price = models.DecimalField(....)
class Transaction(models.Model)
# You have to define related_name for at least one of relations below.
# Without that, automatically generated ones will clash.
# Also don't foget to change `on_delete` to suit your needs.
current_product = models.ForeignKey(Product, related_name="current_transactions", on_delete=models.CASCADE)
previous_product = models.ForeignKey(Product, related_name="previous_transactions", on_delete=models.CASCADE)
#property
def status(self):
# also, no need to do additional queries here manually. You can improve
# it further by using `select_related` when querying for transactions.
c_price = self.current_product.price
p_price = self.previous_product.price
if c_price == p_price:
return "Due"
elif c_price > p_price:
return "Upgrade"
else:
return "Downgrade"
With that model structure, finding specific types of transactions will be easier:
upgrade_transactions = Transaction.objects.filter(current_product__price__gt=F('previous_product__price'))
downgrade_transactions = Transaction.objects.filter(current_product__price__lt=F('previous_product__price'))
due_transactions = Transaction.objects.filter(current_product__price=F('previous_product__price'))
I think you could try to use Subquery, OuterRef and .annotate():
if value == 'Upgrade':
return queryset.annotate(
previous_price=Subquery(
Product.objects.filter(
code=OuterRef("previous_product_code")
)[:1]
),
current_price=Subquery(
Product.objects.filter(
code=OuterRef("current_product_code")
)[:1]
),
).filter(current_price__gt=F("previous_price"))
...
Remember that filter() operation, in the end, is a SQL operation and we should take care on the performance issues.
So my advice is: if you need to filter by status, update the status on Product model everytime a transaction is saved. Your application will be faster and will have a cleaner code.
I'm recently trying to build a little web-app with Flask. For the database 'stuff' I use Flask-SQLAlchemy and now I'm trying to get a relationship between two objects going.
I have a 'project' table and a 'file' table and it should be a one-to-many relation, so x files can be associated with one project (actually there are more relations coming in the future when I've figured the current problem out).
I've made a input-mask template so a user can upload a file and link it to a project via a dropdown which is populated with the existing projects stored in its table. Thats the corresponding view:
#app.route('/admin/upload/', methods=('GET', 'POST'))
def upload():
form = forms.UploadForm()
if not os.path.isdir(app.config['UPLOAD_FOLDER']):
os.mkdir(app.config['UPLOAD_FOLDER'])
print('Folder created')
form.projectId.choices = []
for g in models.Project.query.order_by('name'):
form.projectId.choices.append((g.id, g.name))
if form.validate_on_submit():
filename = secure_filename(form.fileUpload.data.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
assocProject = models.Project(name=models.Project.query.filter_by(id=form.projectId.data).first().name)
form.fileUpload.data.save(filepath)
prepedFile = models.File(path=filepath, project=assocProject)
print(prepedFile)
print(form.projectId.data)
db.session.add(prepedFile)
db.session.commit()
return 'success'
else:
filename = None
return render_template('upload.html', form=form, filename=filename)
The prepared file should be an instance of the File-Class which has the linked Project-instance as an attribute, therefore the commit should work.
class Project(db.Model):
__tablename__ = 'project'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
file = db.relationship('File', backref="projects")
post = db.relationship('Post', backref="projects")
def __init__(self, name):
self.name = name
def __repr__(self):
return '<Project %r>' % self.name
class File(db.Model):
__tablename__ = 'file'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
path = db.Column(db.String(64))
type = db.Column(db.String(6))
projectId = db.Column(db.Integer, db.ForeignKey('project.id'))
project = db.relationship('Project', backref='files')
def __init__(self, path, project):
self.path = path
self.project = project
fullName = re.search('[a-zA-Z0-9]*\.[a-zA-Z]{2,}', path)
splitName = fullName.group(0).split('.')
self.name = splitName[0]
self.type = splitName[1]
def __repr__(self):
return '<File %r %r %r %r>' % (self.name, self.type, self.path, self.project)
And now the problem: When I try to upload a file it works and the file information are stored in the file table but it creates a new entry in the project table and link its id to the file entry. E.g., if the project entry looks like: name = TestProj1, id=1 and I try to link the uploaded to the project it will create a second project: name = TestProj1, id=2.
Thats my struggle and I cant figure out whats wrong. Maybe some of you now. I appreciate any help!
P.S. Maybe it is relevant, here the form I wrote:
class UploadForm(Form):
fileUpload = FileField(label='Deine Datei')
projectId = SelectField(u'Projekte', coerce=int)
You create a new Project each time.
assocProject = models.Project(name=models.Project.query.filter_by(id=form.projectId.data).first().name)
This does two things. First, it finds the first project with the specified id. Second, it passes that project's name to Project(), creating a new instance using that same name.
What you really want is
assocProject = models.Project.query.get(form.projectId.data)
I am trying to relate many2one field to another many2one field but return error.
I used on create method didn't work, I tried
jounral = field.Many2one('erp.journal', related="journal_item.journal
worked but on upgrade of database I receive error
There is no reference field journal_id found of journal.entries.
Here is my code
class JournalItem(models.Model):
_name = 'journal.item'
name = fields.Char()
journal = fields.Many2one('erp.journal')
entries = fields.One2many('journal.entries', 'journal_item')
class JournalEntries(models.Model):
_name = 'journal.entries'
#record Created but didn't work
#api.model
def create(self, vals):
vals['journal_id'] = self.journal_item.journal
return super(JournalEntries, self).create(vals)
#Error NoneType object has no attribute 'id'
#api.model
def create(self, vals):
for x in self:
x.journal_id = x.journal_item.journal
return super(JournalEntries, self).create(vals)
journal_item = fields.Many2one('journal.item')
journal_id = fields.Many2one('erp.journal')
Very first you need to understand the #api decorators usage, which decorators should be implemented when.
#api.model does not have any list of recordset, so you can not loop through it.
You can easily achieve this by defining relational field.
class JournalEntries(models.Model):
_name = 'journal.entries'
journal_item = fields.Many2one('journal.item')
journal_id = fields.Many2one(comodel_name='erp.journal', related='journal_item.journal', string='Journal', readonly=True)
Click here to read about #api decorators
I want to add a new field when somebody checks an option in my web page ("Add column 'external id' ")
table = IssueTable(issue_list)
show_ext = request.GET.get('show_ext', 0)
if show_ext:
table._meta.fields = table._meta.fields + ('external_id',)
I thought doing that it was the solution but I didn't succeed. The external_id is part of the model. table._meta.fields doesnt get updated and of course I cannot see the column in the table when this one is rendered.
class IssueTable(tables.Table):
def render_id(self, value, record):
if record.status.upper() in ['RESOLVED', 'INVALID']:
return mark_safe('<s>#%s</s>' % (reverse('issues.views.view', args=(record.pk,)), record.pk))
else:
return mark_safe('#%s' % (reverse('issues.views.view', args=(record.pk,)), record.pk))
def render_title(self, value, record):
return mark_safe('%s' % (reverse('issues.views.view', args=(record.id,)), value))
class Meta(object):
model = Issue
fields = ('id', 'title', 'product', 'type', 'priority', 'status', 'created')
attrs = {'class': 'table table-bordered'}
empty_text = _('No records found')
Any ideas?