I feel like I'm missing something crucial in rest framework that will help me understand this but so far browsing the documentation has not enlightened me.
I have a model Circuit that can have multiple Component models linked to it, this many to many relationship goes through a CicuitHasComponent table. It can also have sub-circuits, so a many to many relationship with itself through CircuitHasCircuit table. I want to show a detail view for the Circuit (using angular JS on the front end) that lists all the Components and sub-Circuits, and allows me to build new sub-object resources in the angular JS and post them. So I have the following serializers
class ComponentSerializer(HyperlinkedModelSerializer):
class Meta:
model = Component
fields = (
'id', 'name'
)
class CircuitHasComponentSerializer(HyperlinkedModelSerializer):
class Meta:
model = CircuitHasComponent
fields = (
'circuit',
'component'
)
class CircuitHasCircuitSerializer(HyperlinkedModelSerializer):
class Meta:
model = CircuitHasCircuit
fields = (
'circuit',
'subcircuit'
)
class CircuitSerializer(HyperlinkedModelSerializer):
components = CircuitHasComponentSerializer(many=True)
subcircuits = CircuitHasCircuitSerializer(many=True)
class Meta:
model = Circuit
fields = (
'id',
'name',
'components',
'subcircuits'
)
I have corresponding ModelViewSets for each serialiser, but I am not sure on the neatest way to GET a specific subset of CircuitHasComponent (f.e.) objects for a given Circuit ID. Nor am I sure how to POST to the CircuitHasComponent view using JS models of the corresponding Circuit and Component.
Should I be using a nested method for this? or should things be broken down further?
Related
I am relatively new to Django Wagtail and I was following the demo from the docs.wagtail.io website which can be found here on how to add a list of Links to a Page using an InlinePanel with Related links
I seem to have reached an error that I donot fully understand it's meaning.
The error says
AttributeError: type object 'BookPageRelatedLinks' has no attribute 'rel'
The code for the demo is as follows
from wagtail.wagtailcore.models import Orderable, Page
from modelcluster.fields import ParentalKey
from wagtail.wagtailadmin.edit_handlers import FieldPanel,InlinePanel
from django.db import models
class BookPage(Page):
# The abstract model for related links, complete with panels
class RelatedLink(models.Model):
title = models.CharField(max_length=255)
link_external = models.URLField("External link", blank=True)
panels = [
FieldPanel('title'),
FieldPanel('link_external'),
]
class Meta:
abstract = True
# The real model which combines the abstract model, an
# Orderable helper class, and what amounts to a ForeignKey link
# to the model we want to add related links to (BookPage)
class BookPageRelatedLinks(Orderable, RelatedLink):
page = ParentalKey('demo.BookPage', related_name='related_links')
content_panels = Page.content_panels + [
InlinePanel('BookPageRelatedLinks', label="Related Links"),
]
My primary objective was to learn this so I can add image links to a sidebar on a BlogPage app I am developing.
Your InlinePanel declaration isn't quite correct - it needs to be:
InlinePanel('related_links', label="Related Links")
Here's what's going on:
By defining a ParentalKey with related_name='related_links', you set up a one-to-many relation called related_links on BookPage. This allows you to retrieve all of the BookPageRelatedLinks objects associated with a given BookPage instance (for example, if your BookPage instance was called page, you could write page.related_links.all()).
The InlinePanel declaration then tells Wagtail to make the related_links property editable within the admin.
The reason you're getting a misleading error message is that you've defined the RelatedLink and BookPageRelatedLinks classes inside the BookPage - which is a little bit unusual, but still valid. This results in BookPageRelatedLinks being defined as a property of BookPage (i.e. BookPage.BookPageRelatedLinks). Then, when Wagtail tries to set up the InlinePanel, it retrieves that property and fails because it's not the expected type of object (it's a class definition, not a relation).
If you write your models file in the more conventional way, with the related models defined below (or above) BookPage:
class BookPage(Page):
content_panels = Page.content_panels + [
InlinePanel('BookPageRelatedLinks', label="Related Links"),
]
# The abstract model for related links, complete with panels
class RelatedLink(models.Model):
title = models.CharField(max_length=255)
link_external = models.URLField("External link", blank=True)
panels = [
FieldPanel('title'),
FieldPanel('link_external'),
]
class Meta:
abstract = True
# The real model which combines the abstract model, an
# Orderable helper class, and what amounts to a ForeignKey link
# to the model we want to add related links to (BookPage)
class BookPageRelatedLinks(Orderable, RelatedLink):
page = ParentalKey('home.BookPage', related_name='related_links')
...then you would get a more informative error: AttributeError: type object 'BookPage' has no attribute 'BookPageRelatedLinks'.
I want to get my object index as a "resource_uri" instead id
I take the usual way I make a model , views , serializers :
class User(BaseModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
models.CharField()
class UserSerailizers(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id','user','formatted_address')
classclass UserList(generics.ListCreateAPIView):
queryset = Image.objects.all()
serializer_class = UserSerializer
when i call < my_domain/user/ > I get this response
{
id:1,
name:'toto'
}
but I want to have an answer to this form:
{
'url': my_domain/user/1/
'name': 'toto'
}
Any thoughts?
If you want a hyperlink instead of a primary key in your model representations, you have to use either HyperlinkedModelSerializer or more generic Serializer along with HyperlinkedIdentityField and/or HyperlinkedRelatedField. The former is probably what you are looking for.
The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys.
See Django REST framework documentation for more details.
As already commented, you need to use the HyperlinkedModelSerializer as you've shown.
The lookup_field attribute should be inside the Meta class.
And the latest and this is a guess: You just have a ListView for your User model. In order to show the detail for the user, you need also the retrieve method. I would recommend you using the ModelViewset so it automatically implements all methods.
I'm developing a system for a University here in Brazil. In this sytem I've got the following models:
- Country;
- State;
- City;
- University;
- Unit;
- Class;
Ok. and the relations are:
- State belongs to Country;
- City belongs to State;
- University belongs to Country (because, in my database, not every country has states registered to it and not every state has citys registered to it, so I could not demand from the user to register a University to a City);
- Unit belongsTo university;
- Class belongs to University (because not every University has Units registered to it);
Ok. I guess now I've set a good background for you guys to understand my situation. Now onto the question itself:
In the Views of my Model Class I wanna display the Country and (IF there are State City). And I may have the need to display such content in other Model views such as Unit and University.
But when I try to do that in my Class model I can only display the country_id. The foreign key in my university database table. And why is that, that is because my Class model belongs to University, so it's pretty easy to access my University's properties. However I do not wish to access the id of the Country, I want it's Name. And maybe in the future I might want other properties, who knows?
HOW DO I DO THAT? How do I access the properties of the Model Country when my Model Class has NO direct relation to it?
many thx hugs and kisses. Hope someone can help me with this one.
p.S:
I've managed a kinda loser solution: In my Class Controller I've done the following (so I can access variables of the Models Country, State and City):
In the View function I've loaded the Models for State and City (the country Model I can access by the relation Class->University->Country);
Then I used a find method to find the respective country, state and city for the Class in question I wanna display in view.ctp. The code follows:
public function view($id = null) {
$this->Class->id = $id;
$this->set('class', $this->Class->read());
$this->loadModel('State');
$this->loadModel('City');
$country = $this->Class->Universsity->Country->find('first', array('conditions' => array('Country.id' => $this->Class->data['University']['country_id']),));
$state = $this->State->find('first', array('conditions' => array('State.id' => $this->Class->data['University']['state_id']),));
$city = $this->City->find('first', array('conditions' => array('City.id' => $this->Class->data['University']['city_id']),));
$this->set('country',$country['Country']);$this->set('city',$city);
$this->set('state',$state);
}
And it kinda works...In my Wiew.ctp I get an array for Country data, and array for State data and an array for City data. And in the view I check to see if the state and city arrays are not length = 0 to display them and all...but I think there HAS to be a better way to do This.
P.P.S:
The other question is...what about the Index.ctp? How will I do that if I do not know which Class I'm working with? Will I have to have logic and find methods in the View? Isin't that just messing up the code?
Without posting your code, it's difficult to point you in the right direction. However, working on the assumption that you have your models configured correctly you should be able to do the following:
ClassController.php
public class ClassController extends AppController{
public $uses = array('Class');
public function view($id){
$class = $this->Class->find('first', array('conditions' => array('Class.id' => $id));
$this->set('class', $class);
}
}
view.ctp
<?php echo $class['Country']['name']?>
You may find however you will have to configure the recursive parameter of your class model so that CakePHP retrieves all the associated data. This can be done one of two ways:
Configure the recursive parameter within your Class model (see the documentation on how to do this). This sets the default value for recursive whenever you retrieve records from the database and you don't specify the attribute in your options.
Set the recurisve parameter within your find(...) method calls. I favor this one because it helps avoid placing a heavy load on the database when you don't need the data it retrieves.
For example, in your controller you could do the following:
public function view($id){
$class = $this->Class->find('first', array('conditions' => array('Class.id' => $id), 'recursive' => 3));
$this->set('class', $class);
}
Just a warning, don't set recursive to a value higher than you need, otherwise you may retrieve stuff that you don't particularly require. Use the debug() function to inspect what you're model is currently retrieving so you can make more of an informed decision:
debug($class);
I hope this is of some help!
I have a course catalogue and am trying to include pre-requisits.
A course has 0 to n pre-requisits and a course can be the pre-quesit for 0 to n courses.
The course class is as follows
class Course(models.Model):
class Meta:
ordering = ['course_code', 'title']
course_id = models.AutoField(primary_key=True)
course_code = models.SlugField(max_length=20, null=False, blank=False)
....
....
class Pre_requisit(models.Model)
course = models.ForeignKey(Course, course_id')
pre_req = ???????
I have tried the pre_req field as a ForeginKey and MamyToManyField but cant find a solution.
Django will not allow 2 ForeignKeys from Pre_requisit class to the Course class.
With the ManyToMany field evn through another table I still get errors.
Can anyone let me know how to acheive this relationship.
I wish to ensure the pre-requisit course exists and be able to link to it so it can be displayed.
Many thanks.
class Course(models.Model):
....
pre_req = models.ManyToManyField("self")
read more at http://docs.djangoproject.com/en/dev/ref/models/fields/#manytomanyfield
If you wish to store extra info you can specify a "through" table also ( info at http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany) such as hard pre-requisite or recommended etc.
Today I've got a problem when I tried using following code to alter the model attribute in the controller
function userlist($trigger = 1)
{
if($trigger == 1)
{
$this->User->useTable = 'betausers'; //'betausers' is completely the same structure as table 'users'
}
$users = $this->User->find('all');
debug($users);
}
And the model file is
class User extends AppModel
{
var $name = "User";
//var $useTable = 'betausers';
function beforeFind() //only for debug
{
debug($this->useTable);
}
}
The debug message in the model showed the userTable attribute had been changed to betausers.And It was supposed to show all records in table betausers.However,I still got the data in the users,which quite confused me.And I hope someone can show me some directions to solve this problem.
Regards
Model::useTable is only consulted during model instantiation (see the API documentation for Model::__construct). If you want to change the model's table on the fly, you should use Model::setSource:
if ( $trigger == 1 ) {
$this->User->setSource('betausers');
}
The table to use is "fixed" when the model is loaded/instantiated. At that time a DB connection object is created, the table schema is being checked and a lot of other things happen. You can change that variable later all you want, Cake is not looking at it anymore after that point.
One model should be associated with one table, and that association shouldn't change during runtime. You'll need to make another model BetaUser and dynamically change the model you're using. Or rethink your database schema, a simple flag to distinguish beta users from regular users within the users table may be better than a whole new table.