Manage ManyToMany relationship in Websauna Admin Panel - sqlalchemy

I have a model where a lot of ManyToMany connections. I need a smart way to manage from Admin Panel. When creating a campaign model I need to connect to other models. Does Websauna have something like Django Inline foms?
class Campaign(Base, BaseMixin):
name = Column(String())
created_at = Column(UTCDateTime, default=now, nullable=False)
updated_at = sa.Column(UTCDateTime, onupdate=now)
owner_id = Column(ForeignKey('users.id'))
workers = relationship('Worker',
secondary=CampaignWorker.__table__,
back_populates='campaign')
recipients = relationship('Recipient',
secondary=CampaignRecipient.__table__,
back_populates='campaign')
accounts = relationship('Account',
secondary=CampaignAccount.__table__,
back_populates='campaign')
messages = relationship('Message',
back_populates='campaign')
message_deliveries = relationship('MessageDelivery',
secondary=CampaignMessageDelivery.__table__,
back_populates='campaign')

Deform can do inline forms as sequences.
However, as automatically generating forms from ManyToMany relationships is complex, you need to manually construct the Deform schema.
You can do this by overriding FormView.create_form() that returns a deform.Form object with your custom schema with sequences.
Then, you need to also override Edit.save_changes() and/or Add.build_object() that would read incoming appstruct (dict) and create or update objects in ManyToMany relationships.

Related

Display on a map objects matching a queryset with Django

I have a Django app, where each user can add a product with multiple possible metrics (width, height and length combination). A user must also specify in which city this product is located.
Users can also search within the database all products matching specific metrics.
I use Django 1.11 and am seaching for a solution to display on an interactive map all the products matching a queryset.
I am trying to do it with django-leaflet and django-geojson (as my db is not gis-oriented and I don't need heavy geo-computations), but I am facing some difficulties because my "PointField" is not in my product Model but in the Location Model and on the map I need to display Product properties, so I must serialize all these data together.
If you prefer code rather than words, here is a simplified version of my relevant files.
#models.py
class Product(models.Model):
name = models.CharField()
owner = models.ForeignKey(User)
photo = models.ImageField(...)
dimensions = models.ManyToManyField(Metrics)
location = models.ForeignKey(Location, related_name='products', related_query_name='product')
class Metrics(models.Model):
width = models.PositiveIntegerField()
height = models.PositiveIntegerField()
length = models.PositiveIntegerField()
class Location(models.Model):
zip_code = models.PositiveIntegerField()
city_name = models.CharField()
slug = models.SlugField(max_length=500, blank=True)
geom = PointField(default={'type': 'Point', 'coordinates': [0, 0]})
#views.py
class SearchResultListView(ListView):
model = models.Product
template_name='my_app/searchresult_list.html'
context_object_name = 'product_list'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
query_width = self.request.GET['width']
query_height = self.request.GET['height']
query_length = self.request.GET['length']
context['product_list'] = context['product_list'].filter(metrics__width=query_width,
metrics__length=query_length, metrics__height=query_height)
return context
#urls.py
????
#template.html
????
I saw in the django-geojson documentation multiple ways to hit the db (GeoJSON layer view,
Tiled GeoJSON layer view, GeoJSON template filter, low-level serialization). But I struggle to find the way to match my needs as my properties are in the Product Model, my coordinates are in the Location Model and my queryset in a non-related class-based view.
Any idea on the best way to perform my task? Should I continue with django-geojson or are there better apps for my purpose?
Your Product and Location look OK, but it is not clear what you are trying to do with Metrics. To select products near some place you want something like:
queryset = Product.objects.filter(location__geom__distance_lt=(someLocation, D(m=50)))
https://docs.djangoproject.com/en/3.0/ref/contrib/gis/geoquerysets/#distance-lt

Django how to select foreign value in query

Having following models:
User(models.Model):
...
login = ...
Asset(models.Model):
user = models.ForeignKey(User)
...
How to select users login in Asset query using django QuerySet capabilities. For example:
Asset.objects.extra(select = {'user_login' : 'user__login'})
make to return query set with user_login field in each model object
Each Asset object already has a foreign key to the user. So you can always access -
asset = Asset.objects.get(pk=any_id)
if asset.user.login == 'some_value':
do_some_magic()
Please read the documentation.
Use .select_related('user') to select all assets and related users in a single query. Then simply access it through asset.user.login.
assets = Asset.objects.selec_related('user').filter(<any filter>)
for asset in assets:
# no additional queries here, as the user objects are preloaded into memory
print asset.user.login
I have found following solution:
Asset.object.extra( select = {'user_login' : '`%s.%s`' % (User._meta.db_table, 'login') } ).order_by('user__login')
The order_by expression is used to make JOIN on User's model table, than user's login can be accessed in SELECT expression within user_table.login

Can you include a TaggableManager as a filterset for django-filter?

I'm using both django-taggit and django-filter in my web application, which stores legal decisions. My main view (below) inherits from the stock django-filter FilterView and allows people to filter the decisions by both statutes and parts of statutes.
class DecisionListView(FilterView):
context_object_name = "decision_list"
filterset_class = DecisionFilter
queryset = Decision.objects.select_related().all()
def get_context_data(self, **kwargs):
# Call the base implementation to get a context
context = super(DecisionListView, self).get_context_data(**kwargs)
# Add in querysets for all the statutes
context['statutes'] = Statute.objects.select_related().all()
context['tags'] = Decision.tags.most_common().distinct()
return context
I also tag decisions by topic when they're added and I'd like people to be able to filter on that too. I currently have the following in models.py:
class Decision(models.Model):
citation = models.CharField(max_length = 100)
decision_making_body = models.ForeignKey(DecisionMakingBody)
statute = models.ForeignKey(Statute)
paragraph = models.ForeignKey(Paragraph)
...
tags = TaggableManager()
class DecisionFilter(django_filters.FilterSet):
class Meta:
model = Decision
fields = ['statute', 'paragraph']
I tried adding 'tags' to the fields list in DecisionFilter but that had no effect, presumably because a TaggableManager is a Manager rather than a field in the database. I haven't found anything in the docs for either app that covers this. Is it possible to filter on taggit tags?
You should be able to use 'tags__name' as the search/filter field. Check out the Filtering section on http://django-taggit.readthedocs.org/en/latest/api.html#filtering

assign list elements to database entity in sqlalchemy from a list

I have a simple model as follows, i have a list of games and i want all the players to assign one and only one game, from the list of games. How would i do it in sqlalchemy.
As of now i am using flask sqlalchemy, but the question does not limit to flask-sqlalchemy.
games = ['soccer', 'hockey', 'baseball', 'cricket', 'basketball']
from flask.ext.sqlalchemy import SQLAlchemy
class Gamer(db.Model):
id = db.Column(db.Integer, primary_key=True)
team_name = db.Column(db.String(80))
game_name = db.Column(db.String(80))
game = db.Column(db.String(80), i want only games from the list of games)
The analogous django functionality is found here.
First of all, the django functionality you refer to is not really analogous to the model you list. The reason for this is that Gamer is a model whereas SimpleForm is a UI form.
However, below are few ways you can validate the model:
1) Create a separate tabbe for Games, add the values as rows, and create a N-to-1 relationship from Gamer to the Game. This is readable, and will validate your data on both the business and DB levels
class Game(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80))
class Gamer(db.Model):
# ...
game_id = db.Column(db.Integer, ForeignKey('game.id'))
game = relationship(Game)
2) Create and use a simple validator
from sqlalchemy.orm import validates
class Gamer(db.Model):
# ...
#validates('game')
def validate_game(self, key, address):
assert address in games
return address
edit-1: alternatively, take a look at the The Enum Recipe. But again this is on a model level, not UI validation.

Django - How to link to a legacy database via intermediary?

I have to integrate a legacy design with my Django project and I am looking for some advice on using an intermediary. The existing design works but now I need to filter the Project by a third table.
In english - I have a Organization (Django) and which points to many Projects (Legacy). But all of the Project don't refer to that Organization. I have a third table ProjectMap which was build via a Trigger to address that. It corresponds the Organization.name to a project.
How do I glue this together in order allow me to do this.
projects = Organization.objects.get(pk=1).projects.all()
And it won't get ALL of the projects just the ones which match in the third table. Here is what I have so far..
By the way if anyone has a better strategy I'm all ears
class Organization(models.Model):
name = models.CharField(max_length=32)
projects = models.ManyToManyField(Project)
class Project(models.Model):
"""This is the project info page..
Note: 'id' does exist and is the pk.
"""
result_number = models.IntegerField(null=True, db_column='LBLDGRUNNO', blank=True)
building_number = models.IntegerField(db_column='LBLDGNO')
name = models.CharField(max_length=150, db_column='SPIBLGNAME', blank=True)
class Meta:
db_table = u'PROJINFO'
managed = False
class ProjectMap(models.Model):
projinfo_table_id = models.IntegerField(null=True) # 'id' of Project
name = models.CharField(max_length=128, null=True) # 'name' in Organization
Thanks so much!
Not sure if this is what your asking, but you can use the through call on the ManyToManyField to define an intermediate table:
class Organization(models.Model):
name = models.CharField(max_length=32)
projects = models.ManyToManyField(Project, through="ProjectOrganisation")
class Project(models.Model):
#Stuff Here
class ProjectOrganisation(models.Model):
project = models.ForeignKey(Project)
organization = models.ForeignKey(Organization)
#Other Fields Here
Django does this automatically with manytomany fields anyway, just if you want to add extra fields, this is the way to do it.